DockerFile命令详解
官网命令文档地址:https://docs.docker.com/engine/reference/builder/
Dockerfile由一行行命令语句组成,并且支持以#开头的注释行。
一般Dockerfile分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。
FROM
一个有效的Dockerfile必须以FROM指令开始。
#FROM指令设置基本映像,映像可以是任何有效的映像。--platform:用于指定镜像的平台,例如linux/amd64、linux/arm64、windows/amd64 FROM [--platform=<platform>] <image> [AS <name>] FROM [--platform=<platform>] <image>[:<tag>] [AS <name>] FROM [--platform=<platform>] <image>[@<digest>] [AS <name>] 示例: FROM openjdk:8u282
RUN
RUN指令将在当前映像顶部的新层中执行任何命令
RUN有2种形式:
-
RUN <command>(shell形式,命令在shell中运行,在Linux上默认为 /bin/sh -c,在Windows上默认为cmd/S/C)
-
RUN ["executable", "param1", "param2"] (exec形式,可执行文件,参数)
在shell形式中,可以使用\(反斜杠)将一条RUN指令继续到下一行。
示例:
RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'
也可以合起来:RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
要使用'/bin/sh'以外的其他shell,请使用exec形式:RUN ["/bin/bash", "-c", "echo hello"]
CMD
Dockerfile中只能有一条CMD指令。 如果存在多个CMD,则只有最后一个CMD才会生效。
CMD指令具有三种形式:
-
CMD ["executable","param1","param2"] (exec形式,这是首选的形式,不支持环境变量)
-
CMD ["param1","param2"](用于给ENTRYPOINT传递参数)
-
CMD command param1 param2 (shell形式,支持环境变量)
CMD的主要目的是为执行中的容器提供默认值。
当Dockerfile中同时还有ENTRYPOINT指令时,CMD只能当做其参数使用。
exec表单被解析为JSON数组,这意味着必须在参数周围使用双引号("),而不是单引号(')。
如果用户指定参数来运行docker,那么它们将覆盖CMD中指定的默认值。
RUN与CMD的区别:
RUN实际上运行命令并提交结果; CMD不会在构建时执行任何东西,但会为镜像指定预期的命令。
LABEL
将元数据添加到镜像。一个镜像可以有多个标签。
两种方法:
LABEL multi.label1="value1" multi.label2="value2" other="value3"
LABEL multi.label1="value1" \ multi.label2="value2" \ other="value3"
基础镜像或父镜像(FROM行中的图像)中包含的标签由镜像继承。如果一个标签已经存在,但是有不同的值,那么最近应用的值将覆盖以前设置的任何值。
MAINTAINER
设置生成镜像的作者
MAINTAINER <name>
EXPOSE
在运行时监听指定的网络端口。 可以指定端口是监听TCP还是UDP,如果未指定协议,则默认值为TCP。
# 监听TCP协议 80端口 EXPOSE 80 # 监听UDP协议 80端口 EXPOSE 80/udp # 同时监听TCP、UDP协议 80端口 EXPOSE 80/tcp EXPOSE 80/udp
无论EXPOSE设置如何,都可以在运行时使用-p标志覆盖它们。 例如:
docker run -p 80:80/tcp -p 80:80/udp ...
ENV
允许一次设置多个。
ENV MY_NAME="John Doe" ENV MY_DOG=Rex\ The\ Dog ENV MY_CAT=fluffy ENV MY_NAME="John Doe" MY_DOG=Rex\ The\ Dog \ MY_CAT=fluffy
环境变量默认会在镜像中持久化。如果仅在构建过程中需要环境变量,而在最终映像中则不需要,则执行如下:
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y ...
或者使用ARG,它不会在最终图像中持久化
ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y ...
替代语法:
ENV MY_VAR my-value #省略=
ADD
从<src>复制新的文件、目录或远程文件url,并将它们添加到位于<dest>路径的映像文件系统中。
两种形式:
-
ADD [--chown=<user>:<group>] <src>... <dest>
-
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"] #包含空格使用此方法
# chown特性只支持用于构建Linux容器的Dockerfiles,不适用于Windows容器
可以指定多个<src>资源,但如果它们是文件或目录,它们的路径将被解释为相对于构建上下文的源
示例:
# 添加所有以“hom”开头的文件: ADD hom* /mydir/ # 添加所有hom开头的txt文件 ?被替换为任何单个字符,例如,“home.txt” ADD hom?.txt /mydir/ # <dest>是一个相对路径,或一个相对于WORKDIR的路径,源文件将被复制到目标容器中。 # 添加test.txt文件到 <WORKDIR>/relativeDir/ ADD test.txt relativeDir/ # <dest>是一个绝对路径,添加test.txt文件到 /absoluteDir/ ADD test.txt /absoluteDir/ # 添加包含特殊字符的文件,arr[0].txt ADD arr[[]0].txt /mydir/
<src>路径必须在构建的上下文中;你不能添加../某物/某物,因为docker构建的第一步是发送上下文目录(和子目录)给docker守护进程。 如果<src>是一个URL,而<dest>不以末尾的斜杠结束,则从URL下载一个文件并复制到<dest>。 如果<src>是一个URL,而<dest>确实以一个末尾的斜杠结尾,那么文件名将从URL推断出来,文件将被下载到<dest>/<filename>。例如,添加http://example.com/foobar /将创建文件/foobar。URL必须有一个重要的路径,这样才能在这种情况下发现合适的文件名(http://example.com不起作用)。 如果<src>是一个目录,则复制该目录的全部内容,包括文件系统元数据。目录本身不会被复制,只是它的内容。 如果<src>是一个以可识别的压缩格式(identity、gzip、bzip2或xz)的本地tar存档,那么它将被解压缩为一个目录。远程url中的资源不会解压缩。识别为可识别的压缩格式完全取决于文件的内容,而不是文件的名称。解压缩行为与tar -x相同。 如果<src>是任何其他类型的文件,它会和它的元数据一起单独复制。在这种情况下,如果<dest>以一个末尾的斜杠/结束,它将被认为是一个目录,并且<src>的内容将写入<dest>/base(<src>)。 如果指定了多个<src>资源,或者直接指定,或者使用通配符指定,那么<dest>必须是一个目录,并且必须以斜杠/结束。 如果<dest>没有以尾斜杠结束,它将被认为是一个常规文件,并且<src>的内容将写入<dest>。 如果<dest>不存在,将在其路径中创建所有缺失的目录。
COPY
从<src>复制新的文件、目录或远程文件url,并将它们添加到位于<dest>路径的映像文件系统中。
使用同ADD
ENTRYPOINT
类似于CMD指令,不同的是ENTRYPOINT指令中的命令不能被docker run后续的命令所覆盖,而是将其追加作为参数使用。
如果想要覆盖Dockerfile中的ENTRYPOINT指令,可以在docker run后使用--entrypoint参数来指令新的命令作为入口点。
只有Dockerfile中的最后一条ENTRYPOINT指令才会起作用。
-
ENTRYPOINT ["executable", "param1", "param2"] (exec形式,这是首选的形式,不支持环境变量)
- ENTRYPOINT command param1 param2 (shell形式,支持环境变量)
-
docker run <image>的命令行参数将被附加在exec形式入口点的所有元素之后,并将覆盖使用CMD指定的所有元素。这允许参数被传递给入口点。
-
shell形式禁止使用任何CMD或run命令行参数,但其缺点是入口点将作为/bin/sh -c的子命令启动,该子命令不传递信号,也不会接收到Unix信号。
VOLUME
创建一个挂载点,并将其标记为保存来自本机主机或其他容器的外部挂载卷。
VOLUME ["/data"]
注意事项:
基于windows的容器上的卷:当使用基于windows的容器时,容器中的卷的目标必须是:不存在或为空的目录;C盘以外的驱动器。 从Dockerfile中更改卷:如果任何构建步骤在卷声明后更改了数据,这些更改将被丢弃。 JSON格式:列表被解析为一个JSON数组。必须用双引号(")括起来,而不是单引号(')。 宿主目录是在容器运行时声明的:宿主目录(挂载点)本质上依赖于宿主。这是为了保持映像的可移植性,因为不能保证给定的主机目录在所有主机上都可用。由于这个原因,您不能从Dockerfile中挂载主机目录。卷指令不支持指定host-dir参数。创建或运行容器时,必须指定挂载点。
USER
指定运行容器时的用户名或者用户组。
当为用户指定组时,用户将只有指定的组成员资格。任何其他配置的组成员身份将被忽略。
-
USER <user>[:<group>]
-
USER <UID>[:<GID>]
WORKDIR
设置工作目录。为Dockerfile中的任何运行、CMD、ENTRYPOINT、复制和添加指令设置工作目录。如果工作目录不存在,则会被创建。
WORKDIR /path/to/workdir
WORKDIR指令可以在Dockerfile中使用多次。如果提供了一个相对路径,它将相对于前一个WORKDIR指令的路径。例如:
WORKDIR /a WORKDIR b WORKDIR c RUN pwd $ /a/b/c
WORKDIR指令可以解析之前使用ENV设置的环境变量。你只能使用在Dockerfile中显式设置的环境变量。例如:
ENV DIRPATH=/path WORKDIR $DIRPATH/$DIRNAME RUN pwd $ /path/$DIRNAME
ARG
ARG指令定义了一个变量,用户可以在构建时通过docker build命令使用 --build-arg
<varname>=<value>标志传递给构建器。如果用户指定了一个没有在Dockerfile中定义的构建参数,那么构建将输出一个警告。
可以包含一个或多个ARG指令。
ARG <name>[=<default value>]
默认值
# 如果ARG指令有一个默认值,并且在构建时没有传递值,构建器使用默认值。
ARG user1=someuser
ARG变量定义从Dockerfile中定义的行往后才开始生效。
可以使用ARG或ENV指令来指定RUN指令可用的变量,使用ENV指令定义的环境变量总是覆盖同名的ARG指令。
不建议在构建镜像时使用-build-arg参数来传递如密钥,用户凭据等信息,因为使用docker history命令可以看得到
ONBUILD
添加一个触发器指令,以便在稍后将该映像用作另一个构建的基础时执行。触发器将在下游构建的上下文中执行,就像它在下游Dockerfile中的FROM指令之后被立即插入一样。
任何构建指令都可以注册为触发器。
ONBUILD <INSTRUCTION>
如果正在构建一个映像,它将作为构建其他映像的基础,那么这是非常有用的。
不允许使用ONBUILD ONBUILD链接ONBUILD指令。
STOPSIGNAL
停止信号,类似kill -9。
STOPSIGNAL signal
HEALTHCHECK
检查运行状况。在一定数量的连续失败之后,它就变得不健康。
Dockerfile中只有最后一个健康检查才会生效。
-
HEALTHCHECK [OPTIONS] CMD command (通过在容器中运行命令来检查容器的健康状况)
-
HEALTHCHECK NONE(禁用从基本映像继承的任何健康检查)
--interval = DURATION(时间间隔=持续;默认值:30s) --timeout = DURATION(超时=持续;默认值:30s) --start-period = DURATION(开始时间;默认值:0s) --retries = N(重试;默认值:3)
CMD关键字后面的命令可以是shell命令或exec数组。
健康状态码:
0:成功—容器运行良好,可以使用 1:不健康—容器不能正常工作 2:保留-不使用此退出码
示例:
# 每隔五分钟左右检查一下网络服务器是否能在三秒内提供网站主页 HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
当容器的健康状态发生变化时,将生成一个带有新状态的health_status事件。