
制作镜像的方式
基于容器进行制作
使用 docker commit 命令制作镜像
使用 Dockerfile 制作
编辑 Dockerfile 文件并执行来制作镜像
Dockerfile 简介
只是一个纯文本文件,文本中记录了很多指令。
Dockerfile Format
Format
- # Comment
- INSTRUCTION arguments
指令本身并不区分大小写,但是规范中使用者必须要使用大写。
Docker 是顺序执行的指令,是自上而下执行的
第一个非注释行必须要为 FROM 指令,FROM 指令用来指定基础镜像。
Dockfiler 文件执行
执行环境
必须定义一个执行目录,且 Dockerfile 文件中定义的文件和安装包都需要在这个工作目录中。
可以在该工作目录的子目录,但是不可以在父目录之上。
Dockeringore
该文件也是一个文本文件,称为排除列表,会排除文件中定义的文件。
作用
例如再 Dockerfile 文件中定义了一个目录,但是目录中的有一些文件不需要复制,所以就要可以使用 dockeringore 来定义一些忽略的文件,包括 dockeringore 文件本身。
Docker build 命令的执行逻辑
与另一种就是启动一个容器制作镜像的动作相同,只不过该命令是隐式执行一个容器,并不是在前台执行。
在后端执行的命令与前台执行无异。
在 Dockerfile 中执行的镜像的命令,是要制作基础镜像的命令,并不是宿主机的命令,所以在 Dockerfile 中定义时,必须要使用基础镜像中有的命令。
Environment replacement
该环境变量并不是定义的宿主机或或者是镜像中的环境变量,而是定义的 Dockerfile 文件中定义的环境变量。
高级变量赋值
${variable:-word} 如果 variable 变量没有赋值,那么引用时就是引用的变量后的内容。
${variable:+word} variable 为空那么返回为空,如果 variable 不为空那么返回为 word
镜像制作阶段

第一阶段是使用 docker build 生成镜像
第二阶段是人为的,也就是使用 docker run 命令来生成一个容器并执行
FROM 指令
FROM 指令是最重要的一个且必须为 Dockerfile 文件第一行开头非注释行的第一个,是之后镜像的基准镜像。
基准镜像可以是任何可用镜像文件,docker build 会在 docker 主机上查找指定的镜像文件。如果 docker 主机上没有会从 docker hub regitory 上拉取所需的镜像文件。(并不一定会从 docker hub 拉取,可以自己指定仓库名称)
Syntax
- FROM [:] 或
- FROM @
- 指定作为 base image 的名称
- base image 的标签,为可选项,省略时默认为 latest
范例
FROM busybox@ba65e8d39e89
FROM busybox:latest
MAINTANIER(depreacted)
- 用于让 Dockerfile 制作者提供本人的详细信息
- Dockerfile 并不限制 MAINTANIER 指令可在出现的位置,但推荐将其放置于 FROM 指令之后
Systax
- MAINTANIER <作者名称及邮箱地址>
- MAINTANIER “dingchen<dingchen@134.com>“
LABEL 替代 MAINTANIER
让用户为镜像指定各种元数据
- Syntax: LABEL = = =
范例
MAINTAINER "DINGCHEN <dingchen@123.com>"
LABEL maintainer="dingchen <dingchen@123.com>"
COPY 指令
将宿主机中的文件,打包提供到镜像文件系统中。
Syntax
- COPY …
- COPY [““ … ““]
- :要赋值的源文件或目录,支持使用通配符
- :目标路径,即正在创建的 image 的文件系统路径;建议为 使用绝对路径,否则 COPY 指定则以 WORKDIR 为起始路径
- 当路径中有空白字符时,通常使用第二种格式
- 文件复制准则
- 必须是 build 上下文中的路径,不能是其父目录中的文件
- 如果 是目录,则其内部文件或子目录会被递归复制,但 目录自身不会复制
- 如果指定了多个 ,或在 使用了通配符,则 必须是一个目录,且必须以 / 为结尾
- 如果 事先不存在,那么会将被自动创建,并且包括其父目录路径
范例
COPY index.html /data/html/
制作一个小镜像
dockerfile 文件内容
[root@centos7_10 work]# cat Dockerfile
FROM busybox:latest
MAINTAINER "dingchen <dingchen@134.com>"
COPY index.html /data/html/
[root@centos7_10 work]# docker build -t httpd:v0.1-1 ./
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM busybox:latest
---> f0b02e9d092d
Step 2/3 : MAINTAINER "dingchen <dingchen@134.com>"
---> Running in 27ef549eea77
Removing intermediate container 27ef549eea77
---> 81f66dd6cbed
Step 3/3 : COPY index.html /data/html/
---> e5d096292b50
Successfully built e5d096292b50
Successfully tagged httpd:v0.1-1
验证是否制作成功
[root@centos7_10 work]# docker container run -it httpd:v0.1-1
/ # cat /data/html/index.html
<h1>index.html</h1>
[root@centos7_10 work]# docker container run --rm -it httpd:v0.1-1 cat /data/html/index.html
<h1>index.html</h1>
ADD 指令
- 如果指定的源是一个 URL 会下载数据包
- 如果指定的源是一个 Tar 文件,那么会被自动展开
- 如果指定的源是一个 URL 的 tar 文件则不会被展开
Syntax
- ADD …
- ADD [““…” “]
范例
ADD nginx.tar /usr/local/src
WORKDIR 指令
每次只会影响指令之后的命令,并且该命令指定的是工作目录。设置 WORKDIR 指令后,那么使用 run 命令执行后的容器默认工作目录就是在 WORKDIR 指定的目录中。
指定的是目标地址(也就是容器存储木目录的地址)
范例
完整路径 /usr/local/src
WORKDIR /usr/local/
ADD file.tar ./src
VOLUME
用于在 image 中创建一个挂载点目录,以挂载 Docker host 上的卷或其他容器上的卷。
Syntx
- VOLUME
- VOLUME [““]
如果挂载点目录路径下在此前在文件存在,docker run 命令会在卷挂载完成之后将此前的所有文件复制到新挂在的卷中。
只要镜像中定义了存储卷,那么镜像启动时会自动创建存储卷。
范例
docker file 文件内容
1. 定义 /data/mysql 为挂载点目录
VOLUME /data/mysql/
2. 执行 dockerfile 文件
[root@centos7_10 work]# docker build -t httpd:v0.2 ./
3. 启动容器并查看挂载信息
[root@centos7_10 work]# docker container run --rm -it httpd:v0.2 mount |grep /data/mysql
/dev/mapper/centos-root on /data/mysql type xfs (rw,relatime,attr2,inode64,noquota)
4. 重启容器后会自动挂载
[root@centos7_10 work]# docker container run -it httpd:v0.2
/ # ls /data/mysql/
EXPOSE 指令
为容器打开指定要监听的端口以实现与外部通信,文件中的端口会指定暴露端口,但是不能指定映射后的 IP 和端口。
必须要配合 docker container run 命令中的 -P 命令
Syntax
- EXPOSE [/] [[]…]
- 用于指定传输层协议,可为 tcp 或 udp 两者之一,默认为 tcp 协议
- EXPOSE 指令可以一次指定多个端口
- EXPOSE 11211/udp 11211/tcp
范例
EXPOSE 80/tcp #默认就是暴露 tcp 端口
ENV 指令
用于为镜像定义所需的环境变量,可以被 Dockerfile 文件中位于其后的其他指令所调用
调用格式为 $vairable_name 或 ${variable_name}
Syntax
- ENV
- ENV = …
第一种格式中, 之后的所有内容均会被视作其 的组成部分,因为,一次只能设置一个变量。
第二种格式可以一次设置多个变量,每个变量为一个 “ = ” 的键值对,如果 中包含空格,可以以反斜线进行转义,也可以通过对 加引号进行标识,两外,反斜线也可以用于续行。
定义多个变量时,建议使用第二种方式,以便可以在同一层中完成所有功能。
范例
#默认变量赋值方式
ENV DOC_ROOT /data/html \
WEB_SERVER_PACKAGE="nginx-1.15.2"
COPY index.html ${DOC_ROOT:-/data/html}
ADD ${WEB_SERVER_PACKAGE}.tar.gz /usr/local/src
范例
docker run 命令可以使用 env 选项向变量中传值
在 Dockerfile 中定义的环境变量是可以在之后启动容器时引用环境变量的。
CMD

用来定义 docker run 镜像启动为容器时,默认执行的命令。
比如在 docker run -it [container] [COMMAND] 这条命令后面的 [COMMAND] 代表的就是在制作镜像时 CMD 指定的命令。
CMD 指令的首要目的,在于为启动的容器指定默认要运行的程序,而其运行结束后,容器也将终止。
CMD 指定的命令可以被 docker run 的命令行的选项所覆盖。
在 Dockfile 中可以存在多个 CMD 指令,但仅最后一个会生效。
可以在 docker run 命令执行时运行指定的命令,而不是执行 Dockerfile 中定义的命令
Syntax
- CMD
- CMD [““, “", ““]
- CMD [““, ““]
前两种语法格式的意义同 RUN
第三种则用于为 ENTRYPORINT 指令提供默认参数
RUN
基于 dockerfile 制作镜像时执行的命令,会生成镜像层。
如果命令在镜像中存在关联关系,使用逻辑连接符连接到一起。
使用 RUN 时,命令必须在镜像中存在。
RUN 指令运行于镜像文件构建过程中,而 CMD 指令运行基于 Dockerfile 构建出的新映像文件启动一个容器。
Syntax
- RUN
- RUN [““,”“,”“]
第一种格式中, 通常是一个 shell 命令,并且以 “/bin/sh -c” 来运行,意味着此进程在容器中的 PID 不为 1,不能接受 Unix 信号,因此,当使用 docker stop 命令停止容器时,此进程接收不到 SIGTERM 信号
第二种语法格式中的参数是一个 JSON 格式的数组,其中 为要运行的命令,后面 为传递给命令的选项或参数,然而,此种格式指定的命令不会以 “/bin/sh -c” 来发起,因此常见的 shell 操作变量替换等,不会进行;如果要运行的命令依赖于 shell 特性,那么可以使用
json 数组中,需要使用佛那个双引号
- RUN [“/bin/bash”,”-c”,”“,”“”]
ENTRYPOINT 指令
类似于 CMD 指定的功能,用于为容器指定默认执行程序,从而使得容器像是一个单独的可执行程序
与 CMD 不同的是,由 ENTRYPOING 启动的程序不会被 docker run 命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给 ENTRYPOING 指定指定的程序
但是 docker run 命令的 –entrypoing 选项的参数可覆盖 ENTRYPOING 指令指定的程序
Syntax
- ENTRYPOING
- ENTRYPOING [““,”“,”“]
docker run 命令传入的命令参数会覆盖 CMD 指令的内容并且附加到 ENTRYPOING 命令最后作为参数使用
Dockerfile 文件中也可以存在多个 ENTRYPOING 指令,但是仅有最后一个会生效
如果想要覆盖默认执行命令,那么必须要指定 run 命令的 --entrypoint 指令来实现
如果 entrypoint 指令与 CMD 同时指定,那么就会将 CMD 后的指令或者是参数传递给 entrypoint
范例
CMD 与 ENTRYPOINT 结合,此种方式会启动失败,并且启动时如果指定了命令参数,那么会覆盖 CMD,并执行命令参数
CMD ["/bin/httpd","-f","-h ${WEB_DOC_ROOT}"]
ENTRYPOINT ["/bin/sh","-c"]
这样定义到执行 docker build 后,那么启动容器时执行的命令是 /bin/sh -c /bin/sh -c /bin/httpd -f -h ${WEB_DOC_ROOT}
ENTRYPOINT 指令默认会使用 /bin/sh -c 来运行,如果想要使用自己定义的 /bin/bash 来执行,那么可以使用 ENTRYPOINT ["/bin/bash","-c"] 用数组指定的方式来运行
USER 指令
用于指定运行 image 时的或运行Docker 中任何 RUN、CMD 或 ENTRYPOINT 指令指定的程序时的用户名或者是 UID
默认情况下,container 的运行身份为 root 用户
Syntax
- USER
- 需要注意的是, 可以为任意数字,但实践中其必须为 /etc/passwd 中某用户的有效 UID,否则 docker run 命令将会执行失败
HEALTHCHAECK 指令
检查进程的工作状态。
Syntx
- HELTHCHECK [OPTIONS] CMD command (开启检查)
- OPTIONS 通过定义时间
- –interval 30s 定义检查间隔时间,默认 30s
- –timeout 30s 定义超时时间,默认 30s
- –start-period 5s 主进程初始化时间,默认 0s,类似于 tomcat 必须要等待
- –retries=N 默认为 3 次,检查 3 次后才会认为主进程已死
- 检查后返回值
- 0 成功
- 1 不健康
- 2 预留,可以自己定义
- HELTHCHECK NONE (关闭检查)
范例
HEALTHCHECK --interval=5m --timeout=3s\
CMD curl -f http://localhost/ || exit 1
SHELL 指令
运行程序,默认要使用的 shell 程序,默认是 /bin/sh -c 命令。
STOPSIGNAL 指令
指定关闭的信号名称。
Syntax
- STOPSIGNAL
ARG 指令
只在 docker build 命令中体现,使用 build-arg 命令传参。可以让 Dockerfile 适用于不同版本。
范例
1. 定义引用变量
LABEL maintainer=${author}
2. 赋值变量
ARG author="dingchen <dingchen@123.com>"
docker build --build-arg author="dingchen <dingchen@123.com> -t web:"
ONBUILD
在 Dockerfile 中定义一个触发器。
Dockerfile 用于 build 映像文件,此影响文件亦可作为 base iamge 被另一个 Dockerfile 用作 FROM 指令的参数,并以之构建成新的映像文件。
Syntx
- ONBUILD [INSTRUCTION]
- 不能触发 FROM 和 MAINTAINER 指令
- 使用 ONBUILD 指令的 Dockerfile 构建的镜像应该使用特殊的标签
- 在 ONBUILD 指令中使用 ADD 或 COPY 指令应该格外小心,因为新构建过程的上下文在却笑指定的源文件时会失败