Skip to content

Dockerfile 指令详解

基本语法格式: INSTRUCTION arguments (指令不区分大小写,但必须大写以示区分)

基石与元数据

FROM

必须是 Dockerfile 的第一条非注释指令

  • 作用: 指定基础镜像(你的镜像基于什么系统或环境构建)。
  • 语法:
    • FROM <image> (使用最新版)
    • FROM <image>:<tag> (指定版本,推荐)
    • FROM <image> AS <name> (给阶段起别名,用于多阶段构建)
Dockerfile
FROM node:18-alpine AS builder

LABEL

  • 作用: 给镜像添加元数据(作者、版本、描述等)。以前用 MAINTAINER,现在废弃了,统一用 LABEL
  • 语法: LABEL <key>=<value> <key>=<value> ...
Dockerfile
LABEL version="1.0" description="这是一个Next.js应用" maintainer="yourname@example.com"

文件与目录 (搬运工)

WORKDIR

  • 作用: 设置工作目录。
  • 细节:
    • 相当于 Linux 的 cd
    • 如果目录不存在,Docker 会自动创建。
  • 重要: 后续的 RUNCMDCOPY 指令都会在这个目录下执行。
Dockerfile
WORKDIR /app

COPY

  • 作用: 把宿主机(你的电脑)的文件复制到镜像里。
  • 语法: COPY --chown=<user>:<group> <源路径> <目标路径>
  • 细节: . 代表 WORKDIR 设置的当前目录。
Dockerfile
# 把当前目录所有文件拷到容器当前目录
COPY . .
# 拷贝时同时修改文件权限
COPY --chown=nextjs:nodejs package.json .

ADD (高级版 COPY)

  • 作用: 也是复制文件,但比 COPY 多两个功能:
    • 如果源路径是一个 URL,它会自动下载。
    • 如果源文件是 targzip 等压缩包,它会自动解压。
  • 最佳实践: 官方建议尽量用 COPY,只有在需要自动解压时才用 ADD。
Dockerfile
# 会自动把 html.tar.gz 解压到 /var/www/html
ADD html.tar.gz /var/www/html

变量与环境 (配置)

ENV

  • 作用: 设置环境变量。
  • 生命周期: 构建时有效,容器运行时也有效。
  • 语法: ENV <key>=<value>
Dockerfile
ENV NODE_ENV=production
ENV PORT 3000

ARG

  • 作用: 定义构建时需要的变量。
  • 生命周期: 只在构建过程 (docker build) 中有效,镜像构建好后就消失了。
  • 语法: ARG <name>=<default value>
Dockerfile
# Dockerfile
ARG VERSION=latest
FROM node:${VERSION}

命令行传参: docker build --build-arg VERSION=16 .

执行命令 (核心逻辑)

这是最容易混淆的部分,请注意执行时机的区别。

RUN (构建时执行)

  • 作用: 在生成镜像的过程中执行命令。通常用于安装软件、编译代码。
  • 两种写法:
    • Shell 格式: RUN npm install (相当于在 /bin/sh -c 中运行)
    • Exec 格式(推荐): RUN ["npm", "install"] (类似于函数调用,更安全,但这要求严格的 JSON 格式,必须用双引号)
Dockerfile
# 推荐用 && 连接命令以减少镜像层数
RUN apt-get update && apt-get install -y curl

CMD (启动时默认命令)

  • 作用: 指定容器启动时默认执行的命令。
  • 特点: Dockerfile 中只能有一个 CMD(如果有多个,最后一个生效)。
  • 可覆盖性: 如果你在命令行运行 docker run myimage echo hello,这里的 echo hello 会覆盖 Dockerfile 里的 CMD
  • 语法: CMD ["可执行文件", "参数1", "参数2"]
Dockerfile
CMD ["npm", "start"]

ENTRYPOINT (入口点)

  • 作用: 配置容器启动时的可执行程序。
  • 特点: 很难被覆盖。它让容器看起来像一个二进制可执行程序。
  • 黄金搭档: ENTRYPOINT + CMD 组合使用。ENTRYPOINT 固定命令,CMD 提供默认参数。
Dockerfile
# 这样写,容器就是 Nginx
ENTRYPOINT ["nginx"]
# 默认参数是 -g daemon off;
CMD ["-g", "daemon off;"]

# 效果:
# 运行 docker run my-nginx -> 执行 nginx -g daemon off;
# 运行 docker run my-nginx -t -> 执行 nginx -t (CMD 被替换了,ENTRYPOINT 还在)

网络与存储

EXPOSE

  • 作用: 声明容器打算使用的端口。
  • 注意: 仅作为文档声明,不会自动开启端口映射(除非运行是用 -P 随机端口)。
  • 语法: EXPOSE <port>
Dockerfile
EXPOSE 8080

VOLUME

  • 作用: 声明匿名数据卷。
  • 目的: 告诉 Docker,这个目录里的数据很重要,不要保存在容器的文件系统层里,而应该映射到宿主机。
  • 语法: VOLUME ["/data"]
Dockerfile
VOLUME ["/var/lib/mysql"]

安全与高级 (进阶)

USER

  • 作用: 切换后续命令的执行用户。
  • 场景: 默认是 root,为了安全,生产环境通常切换到普通用户。
Dockerfile
RUN groupadd -r app && useradd -r -g app app
USER app
CMD ["python", "app.py"]

HEALTHCHECK (健康检查)

  • 作用: 告诉 Docker 如何判断容器是不是“活着”且“健康”。
Dockerfile
# 每 5 分钟检查一次,如果访问 localhost 失败则认为不健康
HEALTHCHECK --interval=5m --timeout=3s \
  CMD curl -f http://localhost/ || exit 1

ONBUILD (下游触发器)

  • 作用: 当别的镜像以当前镜像为基础(FROM 你的镜像)时,才会执行的命令。
  • 场景: 制作通用的语言框架镜像(如 Python-Flask 基础镜像)。
Dockerfile
ONBUILD COPY . /app
ONBUILD RUN pip install -r requirements.txt

注意事项

构建时 vs 运行时

初学者最容易混淆的是 RUN 和 CMD 的区别。

指令什么时候执行?作用例子
ARGdocker build传参传入版本号
RUNdocker build制作镜像npm install (把依赖装进镜像)
CMDdocker run启动容器npm start (让服务跑起来)
ENVbuild & run设置环境设置数据库密码