大家好,本文是对 Docker 自定义镜像进行讲解,讲解如何进行构建自己的 Docker 镜像以及 Dockerfile 的操作指令。希望对大家有所帮助
镜像的定制实际上就是定制每一层所添加的配置、文件。我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。
Dockerfile 是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
DockerFile分为四部分组成:基础镜像信、维护者信息、镜像操作指令和容器启动时执行指令。
如下步骤以构建nginx镜像为例讲解构建镜像的所使用的参数
构建所需的文件
[root@ecs dockerfile]# ll
total 6984
-rw-r--r-- 1 root root 143 Oct 13 15:07 Dockerfile
-rw-r--r-- 1 root root 7147520 Oct 13 14:45 nginx.tar
[root@ecs dockerfile]#
文件内容如下:
###########
###########
FROM centos:7 ##基础镜像
ADD nginx.tar /usr/local ##使用的tar包以及解压之后的路径
WORKDIR / ###工作目录
ENV PATH /usr/local/nginx/sbin/:$PATH ###环境变量
EXPOSE 80 ###声明端口
ENTRYPOINT ["nginx"] ##执行的命令
CMD ["-g" , "daemon off;"] ###上述命令执行所需要的参数
############
############
运行命令开始构建镜像
[root@ecs dockerfile]# docker build -t nginx:v4 .
Sending build context to Docker daemon 7.15MB
Step 1/7 : FROM centos:7
---> eeb6ee3f44bd
Step 2/7 : ADD nginx.tar /usr/local
---> Using cache
---> 4a88a896da74
Step 3/7 : WORKDIR /
---> Using cache
---> 6e8c279cc694
Step 4/7 : ENV PATH /usr/local/nginx/sbin/:$PATH
---> Using cache
---> 49a1327c8c18
Step 5/7 : EXPOSE 80
---> Using cache
---> add82ef1f24a
Step 6/7 : ENTRYPOINT ["nginx"] ###会启动容器,id为7ccec9f9eac6
---> Running in 7ccec9f9eac6
Removing intermediate container 7ccec9f9eac6
---> 13ab8a5f416c
Step 7/7 : CMD ["-g" , "daemon off;"] ######会启动容器,id为557b4c5e2b47
---> Running in 557b4c5e2b47
Removing intermediate container 557b4c5e2b47
---> 9a5f6f70e7ce
Successfully built 9a5f6f70e7ce
Successfully tagged nginx:v4
[root@ecs dockerfile]#
######################
######################
使用构建的镜像启动容器测试
[root@ecs ~]# docker run -d --name test -p 81:80 nginx:v4
cf3a492f465feae38839a7c37fd21260e874d9d1444332cbe4be7e6d7e3d3188
####运行curl命令测试镜像
[root@ecs ~]# curl 127.0.0.1:81
Welcome to nginx!
Welcome to nginx!
If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.
For online documentation and support please refer to
nginx.org.
Commercial support is available at
nginx.com.
Thank you for using nginx.
[root@ecs ~]#
以一个镜像为基础,在其上进行定制。上面的用例就是以centos:7为基础,在其基础之上进行修改,定制nginx镜像。基础镜像是必须指定的。而 FROM 就是指定基础镜像,因此一个 Dockerfile 中 FROM是必备的指令,并且必须是第一条指令。
####
FROM centos:7
#####################
除了选择现有镜像为基础镜像外,Docker 还存在一个特殊的镜像,名为 scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。
FROM scratch
如果你以 scratch 为基础镜像的话,意味着不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。
RUN 指令是用来执行命令行命令的。由于命令行的强大能力,RUN 指令在定制镜像时是最常用的指令之一.
其运行格式有以下两种
1:shell格式,
RUN yum install nginx
RUN mkdir /etc/test
Dockerfile 中每一个指令都会建立一层,RUN 也不例外。每一个 RUN 的行为,就和刚才我们手工建立镜像的过程一样:新建立一层,在其上执行这些命令,执行结束后,commit 这一层的修改,构成新的镜像。
上面的这种写法,创建了 2 层镜像。会产生非常臃肿、非常多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。
Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不能超过 42 层,现在是不能超过 127 层。
正确写法如下:
RUN yum install nginx \
&& mkdir /etc/test
2: exec格式,
RUN ["nginx", "-c", "daemon off;"] ###这种格式基本很少用,后面讲到exec的使用方式
CMD命令和RUN命令很相似,格式也是一样的,有shell和exec两种格式,还多个个参数传递的功能
参数列表格式:CMD ["参数1", "参数2"...]。在指定了 ENTRYPOINT指令后,用 CMD 指定具体的参数。
ENTRYPOINT ["nginx"] ##执行的命令
CMD ["-g" , "daemon off;"] ###上述命令执行所需要的参数
注释:
Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用 systemd 去启动后台服务,容器内没有后台服务的概念。不能使用systemd的方式启动。
拷贝文件到容器中,同ADD,只是不支持自动下载和自动解压
COPY ./start.sh /start.sh ###/start.sh为绝对路径
使用 COPY 指令,源文件的各种元数据都会保留。比如读、写、执行权限、文件变更时间等。这个特性对于镜像定制很有用。特别是构建相关文件都在使用 Git 进行管理的时候。
ADD 指令和 COPY 的格式和性质基本一致。
ADD nginx.tar.gz / ###如果是url,会自动下载并解压
在 Docker 官方的 Dockerfile 最佳实践文档 中要求,尽可能的使用 COPY,因为 COPY 的语义很明确,就是复制文件而已,而 ADD 则包含了更复杂的功能,其行为也不一定很清晰。最适合使用 ADD 的场合,就是所提及的需要自动解压缩的场合。
ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。
因此在 COPY 和 ADD 指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。
ENTRYPOINT 的目的和 CMD 一样,都是在指定容器启动程序及参数。ENTRYPOINT 在运行时也可以替代,不过比 CMD 要略显繁琐,需要通过 docker run 的参数 --entrypoint 来指定。
当指定了 ENTRYPOINT 后,CMD 的含义就发生了改变,不再是直接的运行其命令,而是将 CMD 的内容作为参数传给 ENTRYPOINT 指令,如下:
ENTRYPOINT ["nginx"] ##执行的命令
CMD ["-g" , "daemon off;"] ###上述命令执行所需要的参数
设置环境变量,当RUN或者CMD运行命令是,可以调用$ENV进行调用,如下:
ENV PATH /usr/local/nginx/sbin/:$PATH ###此处增加了nginx命令的环境标量,
ENTRYPOINT ["nginx"] ##此处可以直接使用nginx的命令否则只能使用/usr/local/nginx/sbin/nginx
CMD ["-g" , "daemon off;"] ###上述命令执行所需要的参数
也可以设置多个变量
ENV key1=value1 key2=value2
声明容器运行的服务端口,如下:
EXPOSE 80 443 ###只是用于声明,并不是因为这个声明而开启这个端口
这样写有两个好处,一个是帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射;另一个则是在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口
在构建镜像时,指定一些参数,例如:
FROM centos:7
ARG user # ARG user=root
USER $user
###############
这时,我们在docker build时可以带上自定义参数user了,如下所示:
docker build --build-arg user=jiushini .
########################
arg与env的区别
ARG 定义的变量只会存在于镜像构建过程,启动容器后并不保留这些变量
ENV 定义的变量在启动容器后仍然保留
为RUN、CMD、ENTRYPOINT以及COPY和AND设置工作目录
使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不存在,WORKDIR 会帮你建立目录。
WORKDIR /
指明镜像的维护者及其联系方式
MAINTAINER [email protected]
不过,MAINTAINER并不推荐使用,更推荐使用LABEL来指定镜像作者,例如:
LABEL maintainer="jiushini.cn"
告诉Docker如何测试容器以检查它是否仍在工作,即健康检查,如下:
HEALTHCHECK --interval=5m --timeout=3s --retries=3 \
CMD curl -f http:/localhost/ || exit 1
其中,一些选项的说明:
--interval=DURATION (default: 30s):每隔多长时间探测一次,默认30秒
-- timeout= DURATION (default: 30s):服务响应超时时长,默认30秒
--start-period= DURATION (default: 0s):服务启动多久后开始探测,默认0秒
--retries=N (default: 3):认为检测失败几次为宕机,默认3次
一些返回值的说明:
0:容器成功是健康的,随时可以使用
1:不健康的容器无法正常工作
2:保留不使用此退出代码