Dockerfile文件指令
程序员文章站
2022-07-10 22:35:53
...
Dockerfile 文件类似于一个配置文件,Docker 可以通过读取其中的指令来自动构建镜像,官网地址:https://docs.docker.com/engine/reference/builder/。
Dockerfile的内容格式如下:
# comment
# INSTRUCTION arguments
虽然 Dockerfile 并不区分大小写,不过按照惯例,一般指令都大写,以与参数部分区分。
类似于 shell 脚本开头中的“#!/bin/bash”写法,Dockerfile 开头也可有相应的解析指令,其格式如下:
# directive=value (注:不允许跨行)
目前官网上列出的解析指令仅有“escape”,是用来自定义转义字符的,默认是“\”。
下面开始介绍 Dockerfile 文件中各个指令的用法。
* FROM
格式:
FROM image[:tag] 或者 FROM image@digest
关于 FROM 指令,需要注意以下几点:
(1) FROM 为随后的指令设置了一个基础镜像,所以必须在 Dockerfile 的第一个非注释行。
(2) FROM 可以出现多次,以便创建多个镜像。
(3) 当忽略掉 tag 或 digest 时,默认会以 latest 来代替。
* RUN
RUN 指令可用来在当前镜像中执行任意命令,并把执行结果传给 Dockerfile 中的下一步。RUN 指令的格式为:
RUN command 或者 RUN ["executable", "param1", "param2"]
其中,前一种属于“shell”形式,运行命令的 shell 在 Linux 上默认是“/bin/sh -c”,在 Windows 上默认是“cmd /S /C”。运行 shell 是可以通过命令改变的,比如:
RUN /bin/bash -c 'echo $HOME'
后一种属于“exec”形式(它会被解析成 JSON 数组,所以必须用双引号),它可以避免整理 shell 字符串,使用了一个没有包含指定运行 shell 的基础镜像来运行命令。它也可以通过类似下面的命令来使用不同的运行 shell:
RUN ["/bin/bash", "-c", "echo $HOME"]
另外,在“exec”形式中是不会调用命令 shell 的,所以运行 RUN ["echo", "$HOME"]不会对 $HOME 进行变量替换(除非使用类似 RUN ["sh", "-c", "echo $HOME"] 来直接执行shell),因为执行环境变量扩展是 shell 而非 docker 的工作。除此之外,对反斜杠“\”进行转移也是必须的,尤其是在 Windows 类系统上。
RUN 的缓存不会自动失效,除非使用了类似“docker build --no-cache”的命令或使用了 ADD 指令(见下面 ADD 指令部分)。
* CMD
CMD 指令设置了启动镜像后默认要运行的命令,它有以下三种形式:
CMD ["executable", "param1", "param2"] # exec 形式,推荐
CMD ["param1", "param2"] # 默认作为 ENTRYPOINT 指令的参数
CMD command param1 param2 # shell 形式
在一个 Dockerfile 文件中只能有一个 CMD 指令。如果有多个,则只有最后一个生效。
如果用户在运行“docker run”命令时含有参数,则会覆盖掉 CMD 设置的默认对应参数。
* LABEL
LABEL 指令可以为一个镜像创建元数据信息。其格式为:
LABEL key1=value1 key2=value2 ...
其中,当 key 或 value 中含有空格时,应该用引号引起来。另外,LABEL 也支持使用转义符来进行跨行定义。
* EXPOSE
EXPOSE 指令用于向 Docker 表明容器运行时要监听的网络端口。其格式为:
EXPOSE port [port ...]
注意,外部主机是无法访问容器中的端口的,必须使用“docker run”命令的“-p”或“-P”来指定映射端口。
* ENV
该指令可用来设置环境变量。格式为:
ENV key value
ENV key=value ...
当一个容器在镜像中运行时,它的环境变量就会一直存在。用户可以使用命令“docker inspect”来查看环境变量信息,还可使用“docker run --env key=value”来修改。然而,变量持续存在也会带来一些副作用。比如,在 Debian 类的基镜像中使用设置“ENV DEBIAN_FRONTEND noninteractive”就可能造成“apt-get”命令的混乱。要为单个命令设置值,可以使用“RUN key=value command”的形式。
* ADD
ADD 指令可用于复制本地或远程的文件或目录(包括元数据)到镜像中。格式如下:
ADD src1 src2 ... dest
ADD ["src1", ..., "dest"] # 路径中含有空格时
当指定多个 src(包括含有通配符的情况) 时,必须相对于要构建的上下文原目录。
dest 是一个绝对路径或是相对于 WORKDIR 的路径。所有新创建的文件的 UID 和 GID 都是 0。当 src 是一个远程地址时,目标文件的权限将会为 600。
如果镜像是通过传递 Dockerfile 文件给标准输入中“docker build”命令构建而成,此种情况是没有构建上下文的,这就要求 Dockerfile 中只能含有一个 URL 类的 ADD 指令。另外,也可传递压缩文件给“docker build”,不过要求 Dockerfile 位于压缩包中的根目录下,然后剩余的内容就会被当作构建的上下文。
ADD 指令不支持文件权限认证,所以当远程文件受权限保护时,应先用“RUN wget”或者“RUN curl”之类的工具认证掉相应的权限。
当 src 的内容变动时,第一个解析到的 ADD 指令会使随后指令的缓存失效,其中就包括了 RUN 指令。
另外,ADD 遵循下面这些规则:
(1) src 路径要在要构建的上下文中,不能使用类似于“ADD ../something dest”的写法,因为“docker build”的第一步就是发送构建上下文目录给 docker 后台进程。
(2) 如果 src 是一个远程地址,并且 dest 没有以“/”结尾,那么远程文件就会先被下下来,然后再复制到 dest;否则就直接复制到 dest 目录下。
(3) 当 src 是本地压缩文件时,复制之前会先被解压,而远程压缩文件则不会。
(4) 如果 src 是一个其它类型的文件,它就会与它的元数据一起被单独复制。此时,如果 dest 以“/”结尾,它就会被当成是目录,然后把 src 的内容写到 dest/base(src) 中。
(5) 当指定多个 src (包括使用通配符的情况)时,dest 必须是已“/”结尾的目录。
(6) 如果 dest 没有以“/”结尾,那它就会被当成是普通文件,然后 src 的内容就会直接写到 dest 中。
(7) 当 dest 不存在时,它就会被递归创建。
* COPY
格式:
COPY src1 src2 ... dest
COPY ["src1", ..., "dest"] # 路径中含有空格时
COPY 和 ADD 都可以复制 src 的内容到 dest,区别是 COPY 不能复制远程文件,然后其余的规则和限制都一样。
* ENTRYPOINT
ENTRYPOINT 可将容器配置成可执行文件的形式。格式如下:
ENTRYPOINT ["executable", "param1", "param2"] # exec 形式,推荐
ENTRYPOINT command param1 param2 # shell 形式
“docker run image”后的命令行参数会被添加到“exec”形式的 ENTRYPOINT 中,并且会覆盖掉所有 CMD 指定的参数。比如,“docker run image -d”就会把“-d”传给ENTRYPOINT。可以使用“docker run --entrypoint”来覆盖 ENTRYPOINT 指令。
ENTRYPOINT 的“shell”形式会阻止 CMD 和 run 命令行参数的执行,但缺点是会被当成“/bin/sh -c”的子命令,这就意味着容器的 PID 1 将不是该可执行文件,并且也不能接收 UNIX 信号,因此也就不能接收到来自“docker stop container”的 SIGTERM 信号(但 stop 会在超时后*发送一个 SIGKILL 信号来强制停止)。要想它能正确处理信号和作为 PID 1,需要在命令前加上“exec”,比如,“ENTRYPOINT exec top -b”。
另外,也只有最后一个 ENTRYPOINT 会生效。
ENTRYPOINT 和 CMD 都定义了容器运行时要执行的命令,它们的相互关系如下:
(1) Dockerfile 至少要指定一个 CMD 或 ENTRYPOINT。
(2) 当要把容器当成可执行文件时,应该定义 ENTRYPOINT。
(3) CMD 应该用来为 ENTRYPOINT 定义额外的默认参数,或要在容器中执行即席命令时使用。
(4) CMD 会被运行容器时指定的替代参数覆盖。
下表显示了指定不同的 ENTRYPOINT 和 CMD 组合时实际执行的命令情况:
* VOLUME
该指令可用来创建具有指定名字的挂载点,还可用来保存本地主机或其它容器的外部挂载卷。格式为:
VOLUME ["/data", ...]
VOLUME /data ...
“docker run”命令会初始化新创建的挂载点,并保留解析到 VOLUME 之前已存在或生成的数据。
关于 VOLUME 需要注意以下几点:
(1) 当使用 Windows 类容器时,挂载点必须是 a) 不存在或者空目录 b) 不为系统驱动盘 C: 的驱动盘 两者之一。
(2) 在挂载点被声明后又被随后的构建步骤改变的数据不会生效。
(3) 挂载点与主机相关,是在容器运行时声明的。这是为了保持镜像的可移植性,因为一个给定的主机在别的主机上不一定可用。因此,不能在 Dockerfile 中挂载一个主机目录(即挂载点)。VOLUME 也不支持指定一个 host-dir 参数,你必须在创建或运行容器时指定挂载点。
* USER
该指令可用来设置运行镜像和执行随后的 RUN、CMD 及 ENTRYPOINT 等指令时的用户名和UID。格式为:
USER daemon
* WORKDIR
该指令可为随后执行的 RUN 和 CMD 等命令设置工作目录(不存在则创建)。格式为:
WORKDIR /path/to/workdir
WORKDIR 可以指定多次,如果其中含有相对路径,则是相对于其上一个 WORKDIR 而言的。另外,WORKDIR 只能处理使用 ENV 明确设置的环境变量。
* ARG
ARG 指令定义了“docker build --build-arg varname=value”需要的变量,同时该选项设置的值又会反过来影响 Dockerfile 中的 ARG 定义的对应变量的值。格式为:
ARG varname[=defaultValue]
ARG 指令可被使用多次,以定义多个变量。
注意,应该避免使用该指令与“--build-arg”来合作接收敏感信息,因为任意该镜像的用户都可使用“docker history”命令来查看所有构建时的变量值。
ARG 和 ENV 指令定义的变量都可被 RUN 指令使用。ENV 定义的环境变量会覆盖掉之前 ARG定义的同名变量的值(包括“--build-arg”传进来的命令行参数值)。两者结合可产生有用的交互,比如下面这个 Dockerfile 文件:
不同于 ARG,ENV 定义的变量是持久化的,因此可像上面这个例子一样使用 ENV 来长期保存 ARG 接收到的命令行参数到最终镜像中。
Docker 中已经预定义了以下这些 ARG 变量(包括它们的大写形式):
http_proxy, https_proxy, ftp_proxy, no_proxy
虽然 ARG 变量不能持久化,但如果跟以前构建时使用的值不一样时,也还是会影响构建缓存的。
* ONBUILD
ONBUILD 指令可为一个镜像添加触发器指令,当把该镜像作为另一构建过程的基时,就会执行这些触发器指令。格式为:
ONBUILD INSTRUCTION
ONBUILD 的工作方式是这样的:
(1) 当解析到 ONBUILD 指令时,构建器就把这个触发器指令添加到当前正在构建的镜像的元数据中,而并不影响当前的构建过程。
(2) 在构建末尾,触发器指令列表就被存到镜像元数据清单的“OnBuild”关键字之下,可使用“docker inspect”指令查看到。
(3) 之后,可利用 FROM 指令把该镜像当成另一构建过程的基使用。在下游的构建器处理 FROM 指令时,就会按注册顺序依次执行这些触发器指令。任意一个指令执行出错都会造成构建过程的失败。
(4) 构建成功后,触发器就会从最终镜像中移除,因此不能被孙子辈构建过程所继承。
示例:
注意:使用 ONBUILD ONBUILD 来链接 ONBUILD 是不允许的,ONBUILD 指令也不会触发 FROM 和 MAINTAINER 指令。
* STOPSIGNAL
STOPSIGNAL 指令设置了发送给容器以让其终止的信号。格式为:
STOPSIGNAL signalNum/signalName
* HEALTHCHECK
该指令可用来测试一个容器是否正在工作。格式为:
HEALTHCHECK [options] CMD command # 运行容器中的命令来检测容器的健康状态
HEALTHCHECK NONE # 禁用继承自基础镜像的 HEALTHCHECK
其中 CMD 前的 options 选项值有:
(1) --interval=DURATION (default: 30s)
(2) --timeout=DURATION (default: 30s)
(3) --retries=N (default: 3)
它可以检测出一个运行中的 Web 服务器是否出现异常导致不能处理新的连接这类的情况。
当一个容器指定了一个 healthcheck 后,除了正常状态外,它还有一个“健康状态”,它初始时是“starting”。不管以前处于什么状态,只要现在通过了健康检查,它就被当作是“健康的”;而如果连续多次不通过,就被当作是“不健康的”。
在一个 Dockerfile 中,只能存在一个 HEALTHCHECK 指令。
在 CMD 后的命令可以是“shell”形式,也可以是“exec”形式。
该指令的退出状态表面了容器的健康状态。可能的值有:
(1) 0:成功(容器是“健康的”,随时可用)
(2) 1:不健康的(容器不能正确地工作)
(3) 2:保留
下面是一个每隔 5 分钟检测一次某 Web 服务器能否在 3 秒内正确服务主页的示例:
为了帮助调试,任何命令输出的内容都被存到了健康状态之中,可使用“docker inspect”命令查看。
当容器的健康状态改变时,就会产生一个带有新的状态的“health_status”事件。
* SHELL
该指令可用来覆盖“shell”形式的命令的默认执行 shell(Linux 上的默认 shell 是 ["/bin/sh", "-c"],Windows 上的是["cmd", "/S", "/C"])。格式为:
SHELL ["executable", "param"]
SHELL 指令可以出现多次。每个都会覆盖先前的 SHELL,然后被当作随后其它指令的执行 shell。示例:
另外,SHELL 指令还可用来修改 shell 的操作方式。例如,在 Windows 上使用“SHELL cmd /S /C /V:ON|OFF”将会更改环境变量延迟扩展语法。
Dockerfile的内容格式如下:
# comment
# INSTRUCTION arguments
虽然 Dockerfile 并不区分大小写,不过按照惯例,一般指令都大写,以与参数部分区分。
类似于 shell 脚本开头中的“#!/bin/bash”写法,Dockerfile 开头也可有相应的解析指令,其格式如下:
# directive=value (注:不允许跨行)
目前官网上列出的解析指令仅有“escape”,是用来自定义转义字符的,默认是“\”。
下面开始介绍 Dockerfile 文件中各个指令的用法。
* FROM
格式:
FROM image[:tag] 或者 FROM image@digest
关于 FROM 指令,需要注意以下几点:
(1) FROM 为随后的指令设置了一个基础镜像,所以必须在 Dockerfile 的第一个非注释行。
(2) FROM 可以出现多次,以便创建多个镜像。
(3) 当忽略掉 tag 或 digest 时,默认会以 latest 来代替。
* RUN
RUN 指令可用来在当前镜像中执行任意命令,并把执行结果传给 Dockerfile 中的下一步。RUN 指令的格式为:
RUN command 或者 RUN ["executable", "param1", "param2"]
其中,前一种属于“shell”形式,运行命令的 shell 在 Linux 上默认是“/bin/sh -c”,在 Windows 上默认是“cmd /S /C”。运行 shell 是可以通过命令改变的,比如:
RUN /bin/bash -c 'echo $HOME'
后一种属于“exec”形式(它会被解析成 JSON 数组,所以必须用双引号),它可以避免整理 shell 字符串,使用了一个没有包含指定运行 shell 的基础镜像来运行命令。它也可以通过类似下面的命令来使用不同的运行 shell:
RUN ["/bin/bash", "-c", "echo $HOME"]
另外,在“exec”形式中是不会调用命令 shell 的,所以运行 RUN ["echo", "$HOME"]不会对 $HOME 进行变量替换(除非使用类似 RUN ["sh", "-c", "echo $HOME"] 来直接执行shell),因为执行环境变量扩展是 shell 而非 docker 的工作。除此之外,对反斜杠“\”进行转移也是必须的,尤其是在 Windows 类系统上。
RUN 的缓存不会自动失效,除非使用了类似“docker build --no-cache”的命令或使用了 ADD 指令(见下面 ADD 指令部分)。
* CMD
CMD 指令设置了启动镜像后默认要运行的命令,它有以下三种形式:
CMD ["executable", "param1", "param2"] # exec 形式,推荐
CMD ["param1", "param2"] # 默认作为 ENTRYPOINT 指令的参数
CMD command param1 param2 # shell 形式
在一个 Dockerfile 文件中只能有一个 CMD 指令。如果有多个,则只有最后一个生效。
如果用户在运行“docker run”命令时含有参数,则会覆盖掉 CMD 设置的默认对应参数。
* LABEL
LABEL 指令可以为一个镜像创建元数据信息。其格式为:
LABEL key1=value1 key2=value2 ...
其中,当 key 或 value 中含有空格时,应该用引号引起来。另外,LABEL 也支持使用转义符来进行跨行定义。
* EXPOSE
EXPOSE 指令用于向 Docker 表明容器运行时要监听的网络端口。其格式为:
EXPOSE port [port ...]
注意,外部主机是无法访问容器中的端口的,必须使用“docker run”命令的“-p”或“-P”来指定映射端口。
* ENV
该指令可用来设置环境变量。格式为:
ENV key value
ENV key=value ...
当一个容器在镜像中运行时,它的环境变量就会一直存在。用户可以使用命令“docker inspect”来查看环境变量信息,还可使用“docker run --env key=value”来修改。然而,变量持续存在也会带来一些副作用。比如,在 Debian 类的基镜像中使用设置“ENV DEBIAN_FRONTEND noninteractive”就可能造成“apt-get”命令的混乱。要为单个命令设置值,可以使用“RUN key=value command”的形式。
* ADD
ADD 指令可用于复制本地或远程的文件或目录(包括元数据)到镜像中。格式如下:
ADD src1 src2 ... dest
ADD ["src1", ..., "dest"] # 路径中含有空格时
当指定多个 src(包括含有通配符的情况) 时,必须相对于要构建的上下文原目录。
dest 是一个绝对路径或是相对于 WORKDIR 的路径。所有新创建的文件的 UID 和 GID 都是 0。当 src 是一个远程地址时,目标文件的权限将会为 600。
如果镜像是通过传递 Dockerfile 文件给标准输入中“docker build”命令构建而成,此种情况是没有构建上下文的,这就要求 Dockerfile 中只能含有一个 URL 类的 ADD 指令。另外,也可传递压缩文件给“docker build”,不过要求 Dockerfile 位于压缩包中的根目录下,然后剩余的内容就会被当作构建的上下文。
ADD 指令不支持文件权限认证,所以当远程文件受权限保护时,应先用“RUN wget”或者“RUN curl”之类的工具认证掉相应的权限。
当 src 的内容变动时,第一个解析到的 ADD 指令会使随后指令的缓存失效,其中就包括了 RUN 指令。
另外,ADD 遵循下面这些规则:
(1) src 路径要在要构建的上下文中,不能使用类似于“ADD ../something dest”的写法,因为“docker build”的第一步就是发送构建上下文目录给 docker 后台进程。
(2) 如果 src 是一个远程地址,并且 dest 没有以“/”结尾,那么远程文件就会先被下下来,然后再复制到 dest;否则就直接复制到 dest 目录下。
(3) 当 src 是本地压缩文件时,复制之前会先被解压,而远程压缩文件则不会。
(4) 如果 src 是一个其它类型的文件,它就会与它的元数据一起被单独复制。此时,如果 dest 以“/”结尾,它就会被当成是目录,然后把 src 的内容写到 dest/base(src) 中。
(5) 当指定多个 src (包括使用通配符的情况)时,dest 必须是已“/”结尾的目录。
(6) 如果 dest 没有以“/”结尾,那它就会被当成是普通文件,然后 src 的内容就会直接写到 dest 中。
(7) 当 dest 不存在时,它就会被递归创建。
* COPY
格式:
COPY src1 src2 ... dest
COPY ["src1", ..., "dest"] # 路径中含有空格时
COPY 和 ADD 都可以复制 src 的内容到 dest,区别是 COPY 不能复制远程文件,然后其余的规则和限制都一样。
* ENTRYPOINT
ENTRYPOINT 可将容器配置成可执行文件的形式。格式如下:
ENTRYPOINT ["executable", "param1", "param2"] # exec 形式,推荐
ENTRYPOINT command param1 param2 # shell 形式
“docker run image”后的命令行参数会被添加到“exec”形式的 ENTRYPOINT 中,并且会覆盖掉所有 CMD 指定的参数。比如,“docker run image -d”就会把“-d”传给ENTRYPOINT。可以使用“docker run --entrypoint”来覆盖 ENTRYPOINT 指令。
ENTRYPOINT 的“shell”形式会阻止 CMD 和 run 命令行参数的执行,但缺点是会被当成“/bin/sh -c”的子命令,这就意味着容器的 PID 1 将不是该可执行文件,并且也不能接收 UNIX 信号,因此也就不能接收到来自“docker stop container”的 SIGTERM 信号(但 stop 会在超时后*发送一个 SIGKILL 信号来强制停止)。要想它能正确处理信号和作为 PID 1,需要在命令前加上“exec”,比如,“ENTRYPOINT exec top -b”。
另外,也只有最后一个 ENTRYPOINT 会生效。
ENTRYPOINT 和 CMD 都定义了容器运行时要执行的命令,它们的相互关系如下:
(1) Dockerfile 至少要指定一个 CMD 或 ENTRYPOINT。
(2) 当要把容器当成可执行文件时,应该定义 ENTRYPOINT。
(3) CMD 应该用来为 ENTRYPOINT 定义额外的默认参数,或要在容器中执行即席命令时使用。
(4) CMD 会被运行容器时指定的替代参数覆盖。
下表显示了指定不同的 ENTRYPOINT 和 CMD 组合时实际执行的命令情况:
* VOLUME
该指令可用来创建具有指定名字的挂载点,还可用来保存本地主机或其它容器的外部挂载卷。格式为:
VOLUME ["/data", ...]
VOLUME /data ...
“docker run”命令会初始化新创建的挂载点,并保留解析到 VOLUME 之前已存在或生成的数据。
关于 VOLUME 需要注意以下几点:
(1) 当使用 Windows 类容器时,挂载点必须是 a) 不存在或者空目录 b) 不为系统驱动盘 C: 的驱动盘 两者之一。
(2) 在挂载点被声明后又被随后的构建步骤改变的数据不会生效。
(3) 挂载点与主机相关,是在容器运行时声明的。这是为了保持镜像的可移植性,因为一个给定的主机在别的主机上不一定可用。因此,不能在 Dockerfile 中挂载一个主机目录(即挂载点)。VOLUME 也不支持指定一个 host-dir 参数,你必须在创建或运行容器时指定挂载点。
* USER
该指令可用来设置运行镜像和执行随后的 RUN、CMD 及 ENTRYPOINT 等指令时的用户名和UID。格式为:
USER daemon
* WORKDIR
该指令可为随后执行的 RUN 和 CMD 等命令设置工作目录(不存在则创建)。格式为:
WORKDIR /path/to/workdir
WORKDIR 可以指定多次,如果其中含有相对路径,则是相对于其上一个 WORKDIR 而言的。另外,WORKDIR 只能处理使用 ENV 明确设置的环境变量。
* ARG
ARG 指令定义了“docker build --build-arg varname=value”需要的变量,同时该选项设置的值又会反过来影响 Dockerfile 中的 ARG 定义的对应变量的值。格式为:
ARG varname[=defaultValue]
ARG 指令可被使用多次,以定义多个变量。
注意,应该避免使用该指令与“--build-arg”来合作接收敏感信息,因为任意该镜像的用户都可使用“docker history”命令来查看所有构建时的变量值。
ARG 和 ENV 指令定义的变量都可被 RUN 指令使用。ENV 定义的环境变量会覆盖掉之前 ARG定义的同名变量的值(包括“--build-arg”传进来的命令行参数值)。两者结合可产生有用的交互,比如下面这个 Dockerfile 文件:
FROM ubuntu ARG CONT_IMG_VAR ENV CONT_IMG_VAR ${CONT_IMG_VAR:-v1.0.0} RUN echo $CONT_IMG_VAR
不同于 ARG,ENV 定义的变量是持久化的,因此可像上面这个例子一样使用 ENV 来长期保存 ARG 接收到的命令行参数到最终镜像中。
Docker 中已经预定义了以下这些 ARG 变量(包括它们的大写形式):
http_proxy, https_proxy, ftp_proxy, no_proxy
虽然 ARG 变量不能持久化,但如果跟以前构建时使用的值不一样时,也还是会影响构建缓存的。
* ONBUILD
ONBUILD 指令可为一个镜像添加触发器指令,当把该镜像作为另一构建过程的基时,就会执行这些触发器指令。格式为:
ONBUILD INSTRUCTION
ONBUILD 的工作方式是这样的:
(1) 当解析到 ONBUILD 指令时,构建器就把这个触发器指令添加到当前正在构建的镜像的元数据中,而并不影响当前的构建过程。
(2) 在构建末尾,触发器指令列表就被存到镜像元数据清单的“OnBuild”关键字之下,可使用“docker inspect”指令查看到。
(3) 之后,可利用 FROM 指令把该镜像当成另一构建过程的基使用。在下游的构建器处理 FROM 指令时,就会按注册顺序依次执行这些触发器指令。任意一个指令执行出错都会造成构建过程的失败。
(4) 构建成功后,触发器就会从最终镜像中移除,因此不能被孙子辈构建过程所继承。
示例:
[...] ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src [...]
注意:使用 ONBUILD ONBUILD 来链接 ONBUILD 是不允许的,ONBUILD 指令也不会触发 FROM 和 MAINTAINER 指令。
* STOPSIGNAL
STOPSIGNAL 指令设置了发送给容器以让其终止的信号。格式为:
STOPSIGNAL signalNum/signalName
* HEALTHCHECK
该指令可用来测试一个容器是否正在工作。格式为:
HEALTHCHECK [options] CMD command # 运行容器中的命令来检测容器的健康状态
HEALTHCHECK NONE # 禁用继承自基础镜像的 HEALTHCHECK
其中 CMD 前的 options 选项值有:
(1) --interval=DURATION (default: 30s)
(2) --timeout=DURATION (default: 30s)
(3) --retries=N (default: 3)
它可以检测出一个运行中的 Web 服务器是否出现异常导致不能处理新的连接这类的情况。
当一个容器指定了一个 healthcheck 后,除了正常状态外,它还有一个“健康状态”,它初始时是“starting”。不管以前处于什么状态,只要现在通过了健康检查,它就被当作是“健康的”;而如果连续多次不通过,就被当作是“不健康的”。
在一个 Dockerfile 中,只能存在一个 HEALTHCHECK 指令。
在 CMD 后的命令可以是“shell”形式,也可以是“exec”形式。
该指令的退出状态表面了容器的健康状态。可能的值有:
(1) 0:成功(容器是“健康的”,随时可用)
(2) 1:不健康的(容器不能正确地工作)
(3) 2:保留
下面是一个每隔 5 分钟检测一次某 Web 服务器能否在 3 秒内正确服务主页的示例:
... HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost || exit 1 ...
为了帮助调试,任何命令输出的内容都被存到了健康状态之中,可使用“docker inspect”命令查看。
当容器的健康状态改变时,就会产生一个带有新的状态的“health_status”事件。
* SHELL
该指令可用来覆盖“shell”形式的命令的默认执行 shell(Linux 上的默认 shell 是 ["/bin/sh", "-c"],Windows 上的是["cmd", "/S", "/C"])。格式为:
SHELL ["executable", "param"]
SHELL 指令可以出现多次。每个都会覆盖先前的 SHELL,然后被当作随后其它指令的执行 shell。示例:
FROM microsoft/windowsservercore # Executed as cmd /S /C echo default RUN echo default # Executed as cmd /S /C powershell -command Write-Host default RUN powershell -command Write-Host default # Executed as powershell -command Write-Host hello (more efficient) SHELL ["powershell", "-command"] RUN Write-Host hello # Executed as cmd /S /C echo hello (more efficient) SHELL ["cmd", "/S"", "/C"] RUN echo hello
另外,SHELL 指令还可用来修改 shell 的操作方式。例如,在 Windows 上使用“SHELL cmd /S /C /V:ON|OFF”将会更改环境变量延迟扩展语法。