文章目录
1. dockerfile 是什么 ?
1. 定义
dockerfile 是用来构建 Docker 镜像的构建文件,是由一系列命令和参数构成的脚本
2. 文件实例
以 centos 为例
FROM scratch
ADD centos-8-container.tar.xz /
LABEL org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20190927"
CMD ["/bin/bash"]
3. dockerfile、Docker 镜像和 Docker 容器的关系
从应用软件的角度来看,Dockerfile、Docker 镜像、Docker 容器分别代表软件开发的三个阶段
- Dockerfile 是软件的原材料,包括执行代码、文件、环境变量、依赖包、运行时环境等,面向开发
- Docker 镜像是软件的交付品,由 dockerfile 文件运行 docker build 指令生成,成为交付标准
- Docker 容器可以认为是软件的运行态,当运行 Docker 镜像时,真正开始提供服务,涉及运维和部署
三者缺一不可,合力充当 Docker 体系的基石
2. dockerfile 基础知识
1. dockerfile 语法
- 每条保留字指令都必须为大写字母且后面至少跟随一个参数
- 指令按照从上到下,顺序执行
- # 表示注释
- 每条指令都会创建一个新的镜像层,并对镜像进行提交
2. dockerfile 执行流程
- docker 从基础镜像运行一个容器
- 执行一条指令并对容器进行修改
- 执行类似 docker commit 的操作提交一个新的镜像层
- docker 再基于刚提交的镜像运行一个新容器
- 执行 dockerfile 中的下一条指令直到所有指令偶执行完成
3. dockerfile 保留字指令
保留字指令 | 作用 | 备注 |
---|---|---|
FROM | 基础镜像,当前新镜像是基于哪个镜像的 | |
MAINTAINER | 作者+作者邮箱 | |
RUN | 镜像构建时需要运行的命令 | |
EXPOSE | 当前容器对外暴露的端口 | |
WORKDIR | 指定创建容器后,终端默认登陆时进入的工作目录 | |
ENV | 构建镜像中设置环境变量 | |
ADD | 将宿主机目录下的文件拷贝进镜像 | 会自动处理URL和解压tar |
COPY | 将宿主机目录下的文件拷贝进镜像 | 不会自动处理URL,也不解压tar |
VOLUME | 容器数据卷,用于数据保存和持久化工作 | |
CMD | 指定一个容器启动时要运行的命令 | 存在多个CMD指令,只生效最后一个,docker run 之后的参数会覆盖原来参数 |
ENTRYPOINT | 指定一个容器启动时要运行的命令 | 存在多个ENTRYPOINT指令,只生效最后一个,docker run 之后的参数会追加到原来参数列表中 |
ONBUILD | 当父镜像被子镜像继承时,父镜像的ONBUILD被触发 |
4. dockerfile 使用案例
1. 自定义 centos 镜像
-
默认 centos 镜像情况
- 运行该镜像默认进入 / 目录
- 不支持 vim
- 不支持 ifconfig
-
编写自己的 dockerfile 文件
# 当前镜像基于 centos 镜像 FROM centos # 作者+邮箱 MAINTAINER lyy<[email protected]> # 设置环境变量 ENV MYPATH /tmp # 设置镜像运行落脚点 WORKDIR $MYPATH # 运行yum命令安装vim RUN yum -y install vim # 运行yum命令安装net-tools RUN yum -y install net-tools # 向外暴露80端口 EXPOSE 80 # 指定容器启动时运行的命令 CMD /bin/bash
-
运行构建命令
# 将 /mydocker/dockerFile 文件构建成名为 mycentos 版本号为 1.3 的镜像 docker build -f /mydocker/dockerFile -t mycentos:1.3 .
-
运行构建出的镜像
docker run -it mycentos:1.3
2. CMD 和 ENTRYPOINT 的区别
-
共同点
都是指定一个容器启动时要运行的命令,且只生效最后一个
-
区别
-
使用 CMD 作为 dockerfile 命令
-
编写 dockerFile2
FROM centos RUN yum -y install curl CMD ["curl","-s","http://www.baidu.com"]
-
构建镜像
docker build -f /mydocker/dockerFile2 -t myip .
-
运行容器
docker run myip
curl 命令将 www.baidu.com 的 html 内容显示到控制台
当给 curl 加上 -i 参数,表示显示内容中加上协议头
当运行:
docker run myip -i
报错:
docker: Error response from daemon: OCI runtime create failed: container_linux.go:346: starting container process caused “exec: “-i”: executable file not found in $PATH”: unknown.
-
-
使用 ENTRYPOINT 作为 dockerfile 命令
-
编写 dockerFile3
FROM centos RUN yum -y install curl # 将 CMD 替换为 ENTRYPOINT ENTRYPOINT ["curl","-s","http://www.baidu.com"]
-
构建镜像
docker build -f /mydocker/dockerFile3 -t myip2 .
-
运行容器
docker run myip2
输出结果与前面包含 CMD 命令的 dockerfile 一致
当运行:
docker run myip -i
正确输出协议头和 html 内容
-
-
CMD 和 ENTRYPOINT 的区别在于,CMD 将 docker run 后面的参数替换为要执行的参数;而 ENTRYPOINT 将 docker run 后面的参数追加到要执行的命令中
-
3. 自定义 tomcat9
-
编写 dockerfile
FROM centos MAINTAINER lyy<[email protected]> # 将宿主机中的文件c复制到容器中 COPY c /usr/local/cincontainer # 解压并拷贝tomcat和jdk ADD apache-tomcat-9.0.30.tar.gz /usr/local/ ADD jdk-8u231-linux-x64.tar.gz /usr/local/ # 运行yum安装vim RUN yum -y install vim ENV MYPATH /usr/local WORKDIR $MYPATH # 设置环境变量 ENV JAVA_HOME /usr/local/jdk1.8.0_231 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.30 ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.30 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin # 暴露端口8080 EXPOSE 8080 # 容器启动时运行 tomcat CMD /usr/local/apache-tomcat-9.0.30/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.30/bin/logs/catalina.out
-
构建镜像
docker build -f /mydocker/tomcat9/dockerfile -t lyytomcat9 .
-
运行容器
docker run -d -p:7777:8080 --name myt9 -v /mydocker/tomcat9/test:/usr/local/apache-tomcat-9.0.30/webapps/test -v /mydocker/tomcat9/tomcat9logs:/usr/local/apache-tomcat-9.0.30/logs lyytomcat9
-d:后台运行
-p:向外映射 7777 端口
–name:重命名
-v:添加容器卷
-
验证
curl localhost:7777
正确返回 tomcat 页面信息
docker exec d67c82132a22 pwd
正确返回容器落脚点
docker exec d67c82132a22 java -version
正确返回 jdk 版本号
参考资料:尚硅谷周阳 Docker 教程