Dockerfile 指令速查
本篇汇总 Dockerfile 的全部指令,以表格为主,方便写镜像时随手翻查。每条指令只给最简语法示例;逐条指令的详细讲解、多阶段构建和构建缓存的原理,见第 5 篇《Dockerfile、BuildKit 与 Buildx》。
指令一览
| 指令 | 作用 | 语法示例 |
|---|---|---|
FROM | 指定基础镜像,必须是第一条指令(之前只允许 ARG 和注释) | FROM node:22-alpine |
RUN | 构建时执行命令,结果固化进镜像层 | RUN apk add --no-cache curl |
CMD | 容器启动时的默认命令,可被 docker run 的参数整体覆盖 | CMD ["node", "server.js"] |
ENTRYPOINT | 容器入口命令,docker run 的参数会追加给它 | ENTRYPOINT ["nginx", "-g", "daemon off;"] |
COPY | 把构建上下文里的文件、目录复制进镜像 | COPY package.json /app/ |
ADD | 类似 COPY,额外支持 URL 下载和自动解压本地 tar 包 | ADD config.tar.gz /etc/app/ |
ENV | 设置环境变量,构建期和容器运行期都生效 | ENV NODE_ENV=production |
ARG | 构建期变量,仅 docker build 时有效,运行期读不到 | ARG APP_VERSION=dev |
WORKDIR | 设置后续指令的工作目录,不存在会自动创建 | WORKDIR /app |
USER | 指定容器内进程的运行用户(用户名或 UID) | USER node |
EXPOSE | 声明容器监听的端口,仅作文档说明,不做实际映射 | EXPOSE 3000 |
VOLUME | 声明匿名卷挂载点,数据不写进镜像层 | VOLUME ["/data"] |
LABEL | 以键值对形式给镜像添加元数据 | LABEL org.opencontainers.image.title="myapp" |
HEALTHCHECK | 定义容器健康检查的方式和频率 | HEALTHCHECK --interval=30s CMD curl -f http://localhost:3000/healthz |
SHELL | 更改 shell 形式指令使用的默认解释器 | SHELL ["/bin/bash", "-c"] |
ONBUILD | 设置触发器,本镜像被当作基础镜像时才会执行 | ONBUILD COPY . /app/src |
STOPSIGNAL | 指定 docker stop 时发给容器的信号 | STOPSIGNAL SIGTERM |
MAINTAINER | 维护者信息(已废弃,改用 LABEL) | LABEL maintainer="you@example.com" |
易混指令辨析
- COPY 与 ADD:日常一律用
COPY,只有需要「自动解压本地 tar 包」或「从 URL 直接下载」这两个ADD独有功能时才用ADD。 - CMD 与 ENTRYPOINT:
CMD是默认命令、会被docker run后面的参数整体替换,ENTRYPOINT是固定入口、参数只会追加给它,常见搭配是ENTRYPOINT定程序、CMD定默认参数。 - ENV 与 ARG:
ARG只在构建期存在、构建结束就没了,ENV会永久写进镜像、构建期和运行期都能读到,两者都不要放密钥(会留在镜像和构建历史里)。
exec 形式与 shell 形式
RUN、CMD、ENTRYPOINT 这三条指令都有两种写法,行为差别很大:
| 形式 | 写法示例 | 特点 |
|---|---|---|
| exec 形式(推荐) | CMD ["node", "server.js"] | JSON 数组,直接执行程序、不经过 shell;容器主进程就是程序本身,能正常接收停止信号;不支持变量展开和管道 |
| shell 形式 | CMD node server.js | 经 /bin/sh -c 包装执行,支持变量展开、重定向、管道;容器主进程是 sh,信号传递需要额外处理 |
备注
SHELL 指令可以更换 shell 形式所用的解释器,比如换成 ["/bin/bash", "-c"]。exec 形式不受 SHELL 影响。
常用组合示例
Node 应用
# syntax=docker/dockerfile:1
FROM node:22-alpine
WORKDIR /app
# 先复制依赖清单单独装依赖,源码变动时这层缓存仍有效
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY . .
ENV NODE_ENV=production
EXPOSE 3000
USER node
CMD ["node", "server.js"]
静态站点(nginx)
FROM nginx:alpine
# 把构建产物(如 npm run build 生成的 dist 目录)复制到站点根目录
COPY dist/ /usr/share/nginx/html/
# 自定义站点配置(可选),覆盖默认的 default.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
# nginx 基础镜像自带 CMD ["nginx", "-g", "daemon off;"],无需重复声明
Go 多阶段构建
# syntax=docker/dockerfile:1
# 第一阶段:编译出静态二进制
FROM golang:1.23-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /bin/app .
# 第二阶段:只带二进制和 CA 证书,最终镜像极小
FROM alpine:3.21
RUN apk add --no-cache ca-certificates
COPY /bin/app /usr/local/bin/app
EXPOSE 8080
USER nobody
ENTRYPOINT ["app"]
别忘了 .dockerignore
COPY . . 会把整个构建上下文复制进镜像,node_modules、.git、密钥文件这类内容要写进 .dockerignore 排除掉,既能减小镜像体积、提升构建速度,也能避免敏感文件被打进镜像泄漏出去。