视频加载失败

Dockerfile 指令详解

1412 字
7 分钟
Dockerfile 指令详解

什么是 Dockerfile#

Dockerfile 是一个文本文件,其内包含了一条条的 指令 (Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

使用 Dockerfile 构建镜像有以下优势:

  • 自动化:可以通过 docker build 命令自动构建镜像。
  • 可重复性:由于 Dockerfile 是文本文件,可以确保每次构建的结果一致。
  • 版本控制:Dockerfile 可以纳入版本控制系统(如 Git),便于追踪变更。
  • 透明性:任何人都可以通过阅读 Dockerfile 了解镜像的构建过程。

官方文档#

Dockerfile 指令速查表#

指令作用要点备注
FROM指定基础镜像必须是第一条构建指令;只有全局 ARG 能写在它之前scratch 可作为空基础镜像
RUN在新层执行命令合并命令、清理缓存以减小体积每条 RUN 产生一层,多命令用 && 合并
COPY复制文件优先使用,支持 --from--from 可跨构建阶段/镜像复制
ADD更高级的复制自动解压 tar;公开远程 artifact 应配合 --checksum远程 URL 复制不推荐,优先 curl + RUN
CMD容器启动默认命令可被 docker run 参数覆盖一个 Dockerfile 只应有一个 CMD
ENTRYPOINT容器入口点固定启动命令,CMD 作为默认参数推荐 exec form,能正确接收信号
ENV设置环境变量构建时 + 运行时均生效会固化进镜像
ARG构建参数仅构建时生效,FROM 后需重新声明作用域在声明它的构建阶段内
VOLUME定义匿名卷运行时挂载会遮蔽镜像内目录建议放在末尾,避免后续 RUN 写入被丢弃(旧版 builder)
EXPOSE声明端口仅文档作用,不自动映射仍需 -p 或 compose ports 映射
WORKDIR指定工作目录替代 RUN cd,目录不存在会自动创建影响后续 RUN / CMD / COPY 等
USER指定运行用户用户必须已存在gosu 是运行时降权工具,不是指令,常写在 ENTRYPOINT 脚本里
HEALTHCHECK健康检查支持 starting / healthy / unhealthy 状态需配合 --interval、--retries 等参数
ONBUILD延迟执行指令只继承一次,不可级联子镜像构建时才触发,不会传递给孙镜像
LABEL添加元数据推荐 OCI 标准标签替代已弃用的 MAINTAINER
SHELL更改默认 shell推荐 ["/bin/bash", "-o", "pipefail", "-c"]只影响 shell form 的 RUN / CMD / ENTRYPOINT
STOPSIGNAL设置容器停止信号默认 SIGTERM,可改成其他信号影响 docker stop 时发送的信号
MAINTAINER维护者信息已弃用用 LABEL 替代,现代 Dockerfile 不应再使用

最佳实践清单#

🧱 基础与安全#

1. 固定基础镜像版本 不要只用 latest 或宽泛的标签(如 node:21)。为了构建的可复现性和安全性,应固定到具体版本,甚至摘要(digest)。例如 FROM node:21-alpine@sha256:...。

2. 优先使用多阶段构建 将构建环境(编译工具、依赖)与运行环境分离。这能显著减小最终镜像体积,并减少攻击面。

3. 使用非 root 用户运行 在 Dockerfile 中创建用户并切换(USER)。这能限制容器逃逸后的权限。注意,如果基础镜像默认是 root,你需要显式创建用户并授权(例如对工作目录)。

4. 安全地使用构建密钥(Secrets) 不要使用 ARG 或 ENV 传递密码、API Key。使用 RUN --mount=type=secret 临时挂载密钥,这样它们不会留在镜像历史层中。

🚀 构建效率与缓存#

5. 优化指令顺序以利用缓存 将不常变化的指令放在前面(如安装依赖),常变化的放在后面(如拷贝源码)。对于 COPY,先拷贝 package.json / requirements.txt,安装依赖后,再拷贝其余代码。

6. 利用 BuildKit 的缓存挂载(Cache Mounts) 对于包管理器(npm, pip, apt, go mod),使用 RUN --mount=type=cache 来缓存下载的包。这能极大加速重复构建。例如:

RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt

7. 始终使用 .dockerignore 排除 .git、node_modules、构建产物、临时文件等,能减小构建上下文体积,加快传输速度,并避免意外将敏感文件打包进镜像。

8. 合并 RUN 指令并清理 虽然层数不是唯一指标,但合并相关的 RUN(特别是 apt-get update 和 install)可以确保清理操作(如 rm -rf /var/lib/apt/lists/*)在同一层完成,真正减小体积。

📝 指令与可读性#

9. COPY 优先于 ADD COPY 语义更清晰。ADD 仅用于需要自动解压本地 tar 包的场景。从远程 URL 下载应使用 RUN curl/wget,以便在同一层删除文件。

10. 使用 exec 形式(JSON 数组) CMD 和 ENTRYPOINT 应使用 exec 形式(如 CMD ["python", "app.py"]),而不是 shell 形式。这样能正确接收信号,并避免不必要的 shell 解析。

11. 使用 LABEL 替代 MAINTAINER MAINTAINER 已弃用。使用 LABEL 添加元数据,推荐遵循 OCI 标准(如 org.opencontainers.image.authors)。

12. 使用 WORKDIR 而非 RUN cd WORKDIR 更清晰,且能确保后续指令在正确的目录下执行。使用绝对路径。

✨ 现代特性(BuildKit)#

13. 添加语法指令 在 Dockerfile 首行添加 # syntax=docker/dockerfile:1。这能让你使用最新的稳定语法和构建特性(如 cache mount, secret mount)。

14. 为多平台构建做准备 如果你的项目需要跨架构(如交叉编译场景),应使用 docker buildx build --platform 并利用 BUILDPLATFORM / TARGETPLATFORM 参数进行交叉编译,避免 QEMU 模拟带来的性能损耗。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Dockerfile 指令详解
https://astroluxi.top/posts/dockerfile-instructions/
作者
Lux
发布于
2026-09-19
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
Lux
技术学习者 · 机器人爱好者
公告
欢迎来到我的博客!有所记录,有所分享。
分类
标签
最新动态
站点统计
文章
21
分类
5
标签
35
总字数
105,578
运行时长
0 天
最后活动
0 天前
站点信息
构建平台
Cloudflare Pages
博客版本
Firefly v6.16.5
文章许可
CC BY-NC-SA 4.0