六、DockerFlie解析
一、Docker入门系列--Docker 简介
二、Docker入门系列--Docker安装
三、Docker入门系列--Docker常用命令
四、Docker入门系列--Docker镜像
五、Docker入门系列--Docker容器数据卷
六、Docker入门系列--DockerFlie解析
七、Docker入门系列--使用DockerFlie自定义Tomcat镜像
八、Docker入门系列--Docker常用安装
九、Docker入门系列--本地镜像发布到阿里云
十、Docker入门系列--Docker-Compose简介和安装
十一、Docker入门系列--Docker-Compose模板命令
十二、Docker入门系列--Docker-Compose常用命令
十三、Docker入门系列--Portainer可视化Docker
十四、Docker入门系列--Docker搭建部署SpringCloud微服务项目Demo
6.1 Dockerfile简介
Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本
构建三步骤:
-
编写Dockerfile文件:必须符合file规范
-
docker build:
docker build -f /mydocker/Dockerfile -t mrlinxi/centos .
通过docker build获得一个自定义的镜像 -
docker run
文件长什么样?下面就是我们使用的centos的Dockerfile
FROM scratch
ADD centos-7-x86_64-docker.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="20201113" \
org.opencontainers.image.title="CentOS Base Image" \
org.opencontainers.image.vendor="CentOS" \
org.opencontainers.image.licenses="GPL-2.0-only" \
org.opencontainers.image.created="2020-11-13 00:00:00+00:00"
# default cmd
CMD ["/bin/bash"]
6.2 DockerFile构建过程解析
Dockerfile内容基础知识:
-
每条保留字指令都必须为大写字母且后面要跟随至少一个参数
-
指令按照从上到下,顺序执行
-
表示注释
-
每条指令都会创建一个新的镜像层,并对镜像进行提交
Docker执行Dockerfile的大致流程:
-
(1)docker从基础镜像运行一个容器
-
(2)执行一条指令并对容器作出修改
-
(3)执行类似docker commit的操作提交一个新的镜像层
-
(4)docker再基于刚提交的镜像运行一个新容器
-
(5)执行dockerfile中的下一条指令直到所有指令都执行完成
总结:
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,
-
Dockerfile是软件的原材料
-
Docker镜像是软件的交付品
-
Docker容器则可以认为是软件的运行态。
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。
-
Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
-
Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;
-
Docker容器,容器是直接提供服务的。
6.3 DockerFile体系结构(保留字指令)
FROM:基础镜像,当前新镜像是基于哪个镜像的。基于什么镜像进行修改;
MAINTAINER:镜像维护者的姓名和邮箱地址;
RUN:容器构建时需要运行的命令;
EXPOSE:当前容器对外暴露出的端口;
WORKDIR:指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点,没写默认根目录/;
ENV:用来在构建镜像过程中设置环境变量;
例如:ENV MY_PATH /usr/mytest
这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;也可以在其它指令中直接使用这些环境变量。
比如:WORKDIR $MY_PATH
ADD:将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包;
COPY:类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置; COPY src dest COPY ["src", "dest"]
ADD跟COPY的区别在于ADD在复制后会自动解压缩和处理URL,而COPY仅仅进行复制。
VOLUME:容器数据卷,用于数据保存和持久化工作;
CMD:指定一个容器启动时要运行的命令;Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换(后面案例会具体说明);
ENTRYPOINT:指定一个容器启动时要运行的命令;ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数;
CMD与ENTRYPOINT的区别是CMD存在多个时只有最后一个生效以及CMD会被docker run之后的参数替换;而ENTRYPOINT是追加命令。
ONBUILD:当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发
6.4 案例
6.4.1 Base镜像(scratch)
Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的。
6.4.2 自定义镜像mycentos
Hub默认CentOS镜像什么情况:
自定义mycentos目的使我们自己的镜像具备如下:
登陆后的默认路径、vim编辑器、查看网络配置ifconfig支持
安装Centos镜像之后会默认进入根目录,但是不支持vim也不支持ifconfig,因此利用DockerFile创建的时候安装好相关插件以及修改默认根目录
[1] 编写自定义镜像的Dockerfile
我们在宿主机的/mydocker文件夹下,新建一个Dockerfile:vim Dockerfile2,写入下面的内容
from centos --继承自本地镜像
MAINTAINER ylc<[email protected]> --作者和邮箱
ENV mypath /tmp --环境变量
WORKDIR $mypath --默认登陆的进来目录
RUN yum -y install vim --安装vim
RUN yum -y install net-tools
EXPOSE 80 --指定端口
CMD echo $MYPATH --打印内容
CMD echo "success-----ok"
CMD /bin/bash
[2] 构建自定义镜像--docker build
docker build -f /root/mydocker/Dockerfile2 -t mycentos:1.3 .
build语句最后面一个.表示当前目录
[3] 运行自定义镜像--docker run
docker run -it mycentos:1.3
可以看到默认进入的目录是/tmp
[4] 列出镜像的变更历史
docker history 镜像名
每一步都产生了一个镜像,镜像都是层层叠加的,内部像千层饼一样
6.4.3 CMD/ENTRYPOINT 镜像案例
CMD/ENTRYPOINT都是指定一个容器启动时要运行的命令
[1] CMD镜像案例
Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换。
这里以tomcat为例,tomcat的dockerfile最后一句是
正常我们启动tomcat的命令是:docker run -it -p 主机端口:8080 tomcat
现在我们执行这样一句命令:docker run -it -p 8888:8080 tomcat ls -l
这样就相当于在tomcat的dockerfile后面又加了一句CMD ls -l
,因此会覆盖掉之前的语句。
此时tomcat并没有运行,只是查看了默认路径下的文件。
[2] ENTRYPOINT镜像案例
docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合。
制作CMD版可以查询IP信息的容器:
FROM centos
RUN yum install -y curl
CMD [ "curl", "-s", "https://ip.cn" ]
crul命令解释:curl命令可以用来执行下载、发送各种HTTP请求,指定HTTP头部等操作。curl是将下载文件输出到stdout。
使用命令:curl http://www.baidu.com, 执行后,www.baidu.com 的html就会显示在屏幕上了。这是最简单的使用方法。用这个命令获得了 http://curl.haxx.se 指向的页面,同样,如果这里的URL指向的是一个文件或者一幅图都可以直接下载到本地。如果下载的是HTML文档,那么缺省的将只显示文件头部,即HTML文档的header。要全部显示,请加参数 -i
构建镜像:docker build -f /mydocker/Dockerfile3 -t myip .
创建并启动容器:docker run myip
现在返回的是网页的html文件。
如果我们希望显示 HTTP 头信息,就需要加上 -i
参数:
加上-i
后报错了。我们可以看到可执行文件找不到的报错,executable file not found。
之前我们说过,跟在镜像名后面的是 command,运行时会替换 CMD 的默认值。因此这里的 -i 替换了原来的 CMD,而不是添加在原来的 curl -s https://ip.cn 后面。而 -i 根本不是命令,所以自然找不到。那么如果我们希望加入 -i 这参数,我们就必须重新完整的输入这个命令:
docker run myip curl -s https://ip.cn -i
为了解决上述问题,制作ENTROYPOINT版查询IP信息的容器。
FROM centos
RUN yum install -y curl
ENTRYPOINT [ "curl", "-s", "http://ip.cn" ]
docker build -f /mydocker/Dockerfile4 -t myip2
docker run myip2 -i
现在只用追加一个-i
即可打印请求头跟html文件。
[3] ONBUILD案例
直接在Dockerfile4上修改,追加一句ONBUILD RUN echo "father onbuild-----------10086"
然后使用Dockerfile4构建镜像:docker build -f /mydocker/Dockerfile4 -t myip_father .
复制Dockerfile3命名为Dockerfile5,修改Dockerfile5,直接继承自Dockerfile4:
FROM myip_father
RUN yum install -y curl
CMD [ "curl", "-s", "https://ip.cn" ]
使用Dockerfile5构建镜像:docker build -f /mydocker/Dockerfile5 -t myip_son .