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>资源,但如果它们是文件或目录,它们的路径将被解释为相对于构建上下文的源

在<src>是远程文件URL的情况下,目标将拥有600的权限,ADD指令不支持身份验证。

示例:

# 添加所有以“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/
ADD遵循以下规则:
<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(禁用从基本映像继承的任何健康检查)

在CMD之前可以显示的选项是:
--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事件。

 

 

 

posted @ 2021-01-28 17:38  柒月丶  阅读(515)  评论(0编辑  收藏  举报