欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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 组合时实际执行的命令情况:
Dockerfile文件指令
            
    
    博客分类: docker之旅 Dockerfiledocker 
    * 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”将会更改环境变量延迟扩展语法。
  • Dockerfile文件指令
            
    
    博客分类: docker之旅 Dockerfiledocker 
  • 大小: 24.7 KB
相关标签: Dockerfile docker