ᕕ( ᐛ )ᕗ Jimyag's Blog

Dockerfile 关键字以及部分关键字的区别

· 208 字 · 约 1 分钟

本文基于 Docker 官方 Dockerfile 参考 整理所有关键字,并说明几组容易混淆的指令之间的区别。

指令一览

Dockerfile 支持以下指令(按字母序):

指令 说明
ADD 添加本地或远程文件、目录(含 URL、压缩包自动解压)
ARG 声明构建期变量
CMD 指定容器默认要运行的命令或参数
COPY 从构建上下文复制文件、目录到镜像
ENTRYPOINT 指定容器默认的可执行程序
ENV 设置环境变量(写入镜像,运行时可用)
EXPOSE 声明容器监听的端口
FROM 从基础镜像开始新的构建阶段
HEALTHCHECK 配置容器健康检查
LABEL 为镜像添加元数据
MAINTAINER 指定镜像作者(已废弃,建议用 LABEL)
ONBUILD 当本镜像被作为基础镜像使用时触发的指令
RUN 在构建时执行命令,产生新层
SHELL 设置 RUN、CMD、ENTRYPOINT 使用的默认 shell
STOPSIGNAL 设置容器退出时发送的系统信号
USER 设置后续指令及运行时的用户/组
VOLUME 声明挂载点
WORKDIR 设置工作目录

约定上指令用大写,便于与参数区分;指令本身不区分大小写。Dockerfile 必须由 FROM 开头(前面只能有解析器指令、注释和全局 ARG),指令按顺序执行。

解析器指令(Parser directives)

解析器指令写在文件最上方,形式为 # directive=value,不参与构建层。每条指令只能出现一次,且必须出现在任何普通注释或构建指令之前。

  • syntax:指定使用的 Dockerfile 语法版本,例如 # syntax=docker/dockerfile:1 使用最新稳定语法。
  • escape:设置转义符,默认 \;在 Windows 下可设为 ` 避免与路径中的 \ 冲突。
  • check:控制构建检查行为,如 # check=skip=JSONArgsRecommended 跳过指定检查,# check=error=true 让检查失败时构建失败。

Shell 形式与 Exec 形式

RUNCMDENTRYPOINT 都有两种写法:

  • Shell 形式:INSTRUCTION command param1 param2,通过 shell 执行,支持变量替换、多行续行等。
  • Exec 形式:INSTRUCTION ["executable","param1","param2"],按 JSON 数组解析,直接执行可执行文件,不经过 shell,因此不会自动做变量替换(若需要可显式写 ["sh","-c","echo $HOME"])。

Exec 形式中需用双引号,且反斜杠要转义(Windows 路径需写 \\)。

部分关键字的区别

ADD 和 COPY

  • ADD:源可以是「构建上下文中的路径」或「URL」;若源是本地 tar 等归档,会自动解压到目标;行为较多,语义相对复杂。ADD 不支持 --from
  • COPY:只从构建上下文复制本地文件/目录,不解压、不拉 URL;支持 COPY --from=<阶段名|镜像>,可从命名构建阶段或外部镜像复制,多阶段构建时常用。语义单一,可预期性更好。

需要从构建上下文复制文件时,优先用 COPY;要从上一阶段或其它镜像复制时只能用 COPY –from=…;只有需要 URL 或自动解压归档时再用 ADD。

CMD 和 ENTRYPOINT

  • CMD:定义容器默认的「命令或参数」。若 Dockerfile 中有多条 CMD,仅最后一条生效。docker run 末尾若带了参数,会覆盖整条 CMD。
  • ENTRYPOINT:定义容器启动时「固定执行的可执行程序」。docker run 末尾的参数会作为参数传给 ENTRYPOINT,而不是替换 ENTRYPOINT。

常见用法:用 ENTRYPOINT 指定程序(如 ENTRYPOINT ["/app/server"]),用 CMD 提供默认参数(如 CMD ["--port","8080"]);运行时可覆盖 CMD,而 ENTRYPOINT 一般不变(除非用 --entrypoint)。

ARG 和 ENV

  • ARG:仅构建期有效,用于 docker build 时传入或 Dockerfile 内默认值;不会写入最终镜像,容器运行时无法使用。
  • ENV:在构建期和运行期都有效,会写入镜像;容器内可通过环境变量访问。

FROM 之前的 ARG 只能用于 FROM 的镜像名/标签等;若要在阶段内再次使用该 ARG 的默认值,需在阶段内再写一行不带值的 ARG 变量名

环境变量替换

在 Dockerfile 中可用 $var${var} 引用已通过 ENV 定义的变量;部分指令(如 WORKDIRCOPYADDENVEXPOSE 等)由构建器做替换。RUNCMDENTRYPOINT 若用 shell 形式,变量替换由 shell 完成;若用 exec 形式且未通过 shell,则不会做变量替换。

.dockerignore

.gitignore 类似,.dockerignore 可排除构建上下文中不需要的文件,减小上下文体积并避免敏感文件被 COPY/ADD 进镜像。

参考链接:

#Docker #Dockerfile