Dockerfile 最佳实践速查表
本速查表收录了 Dockerfile 中最常用的指令与最佳实践,涵盖基础镜像选择、构建指令、文件操作、启动配置、多阶段构建和常见优化技巧。适合日常编写与优化 Dockerfile 时参考。
基础镜像 (FROM)
选择一个合适的基础镜像是编写 Dockerfile 的第一步。
``dockerfile
# 使用指定版本镜像(推荐)
FROM node:20-alpine
# 使用多阶段构建命名阶段 FROM golang:1.22 AS builder
# 使用精简基础镜像 FROM python:3.12-slim
# 使用 distroless 镜像(仅运行时)
FROM gcr.io/distroless/base-debian12
`
构建指令 (RUN)
在镜像构建过程中执行命令。
`dockerfile
# 合并多个命令减少层数
RUN apt-get update && apt-get install -y \
curl \
git \
&& rm -rf /var/lib/apt/lists/*
# 使用 exec 格式(推荐) RUN ["npm", "install"]
# 设置构建时缓存 RUN --mount=type=cache,target=/root/.npm \ npm install
# 使用 HERE 文档
RUN <`
文件操作 (COPY / ADD)
将文件从构建上下文复制到镜像中。
`dockerfile
# 复制文件(推荐)
COPY package.json package-lock.json ./
# 复制整个目录 COPY src/ /app/src/
# 设置权限 COPY --chown=node:node config/ /app/config/
# 多阶段构建复制产物 COPY --from=builder /app/dist /usr/share/nginx/html
# ADD 自动解压 tar 包
ADD app.tar.gz /opt/app/
`
工作目录与环境变量 (WORKDIR / ENV / ARG)
`dockerfile
# 设置工作目录(推荐使用绝对路径)
WORKDIR /app
# 设置环境变量(运行时可用) ENV NODE_ENV=production \ PORT=3000
# 构建参数(构建时可覆盖) ARG APP_VERSION=1.0.0 ARG BUILD_DATE
# 将构建参数传递给环境变量
ENV APP_VERSION=$APP_VERSION
`
暴露端口与数据卷 (EXPOSE / VOLUME)
`dockerfile
# 声明容器运行时监听的端口
EXPOSE 8080
EXPOSE 443/tcp 80/udp
# 声明挂载点(匿名卷)
VOLUME ["/data", "/var/log"]
`
启动配置 (CMD / ENTRYPOINT)
`dockerfile
# CMD 作为默认命令(可覆盖)
CMD ["node", "server.js"]
CMD npm start
# ENTRYPOINT 作为固定入口 ENTRYPOINT ["docker-entrypoint.sh"] ENTRYPOINT ["nginx", "-g", "daemon off;"]
# 组合使用:ENTRYPOINT + CMD ENTRYPOINT ["python"] CMD ["app.py"]
# SHELL 与 exec 格式
# exec 格式(推荐):CMD ["executable", "param1"]
# shell 格式:CMD command param1
`
用户与标签 (USER / LABEL)
`dockerfile
# 创建用户并切换(安全最佳实践)
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
# 设置镜像元数据
LABEL maintainer="team@example.com"
LABEL version="1.0.0"
LABEL description="Production web application"
`
健康检查 (HEALTHCHECK)
`dockerfile
# 容器健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1
# 禁用继承的健康检查
HEALTHCHECK NONE
`
触发器与其他指令 (ONBUILD / SHELL)
`dockerfile
# 触发器:当此镜像被用作基础镜像时执行
ONBUILD COPY . /app/src
ONBUILD RUN make build
# 自定义 SHELL(Windows 场景)
SHELL ["powershell", "-Command"]
SHELL ["/bin/bash", "-c"]
`
多阶段构建
将构建环境与运行环境分离,大幅减小镜像体积。
`dockerfile
# 第一阶段:编译构建
FROM golang:1.22 AS builder
WORKDIR /build
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o app .
# 第二阶段:运行环境 FROM alpine:3.20 RUN apk add --no-cache ca-certificates tzdata COPY --from=builder /build/app /app EXPOSE 8080 USER 1001 ENTRYPOINT ["/app"]
# 利用命名阶段进行条件构建 FROM node:20-alpine AS base WORKDIR /app COPY package*.json ./
FROM base AS dev RUN npm install --only=development COPY . .
FROM base AS prod
RUN npm install --only=production
COPY . .
`
最佳实践
`dockerfile
# 1. 使用 .dockerignore 排除无关文件
# .dockerignore 内容:
# node_modules
# .git
# *.md
# Dockerfile
# .env
# 2. 按变更频率排序指令(缓存利用) FROM node:20-alpine # 最不易变:包管理文件 COPY package*.json ./ RUN npm install # 最易变:源代码 COPY . .
# 3. 使用精确标签而非 latest # 错误:FROM node:latest # 正确:FROM node:20.11-alpine3.19
# 4. 最小化镜像层数 # 合并多个 RUN 指令 RUN apt-get update && \ apt-get install -y curl git && \ apt-get clean && \ rm -rf /var/lib/apt/lists/*
# 5. 不以 root 运行 RUN adduser -D myuser USER myuser
# 6. 使用 --no-install-recommends RUN apt-get install -y --no-install-recommends curl
# 7. 设置时区和语言环境 ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime ``
基础镜像(4)
| 命令 | 难度 | ||
|---|---|---|---|
FROM node:20-alpine指定基础镜像,使用特定版本标签 | 基础 | FROM node:20-alpine | |
FROM golang:1.22 AS builder命名阶段,用于多阶段构建 | 中级 | FROM golang:1.22 AS builder | |
FROM python:3.12-slim使用精简版基础镜像减小体积 | 基础 | FROM python:3.12-slim | |
FROM gcr.io/distroless/base-debian12使用 distroless 镜像,仅包含运行时 | 高级 | FROM gcr.io/distroless/base-debian12 |
构建指令(9)
| 命令 | 难度 | ||
|---|---|---|---|
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*合并 RUN 指令,安装包后清理缓存 | 基础 | RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* | |
RUN ["npm", "install"]使用 exec 格式运行命令(避免 shell 转义问题) | 中级 | RUN ["npm", "install"] | |
RUN --mount=type=cache,target=/root/.npm npm install使用 BuildKit 缓存挂载加速构建 | 高级 | RUN --mount=type=cache,target=/root/.npm npm install | |
RUN <<EOF set -e\npip install --no-cache-dir -r requirements.txt\nEOF使用 HERE 文档格式的多行 RUN 命令 | 中级 | RUN <<EOF\nset -e\npip install --no-cache-dir -r requirements.txt\nEOF | |
WORKDIR /app设置工作目录(推荐绝对路径) | 基础 | WORKDIR /app | |
ENV NODE_ENV=production PORT=3000设置环境变量(运行时可用) | 基础 | ENV NODE_ENV=production PORT=3000 | |
ARG APP_VERSION=1.0.0声明构建参数,可在构建时通过 --build-arg 覆盖 | 中级 | ARG APP_VERSION=1.0.0 | |
LABEL version="1.0.0" description="Production web application"为镜像添加元数据标签 | 基础 | LABEL version="1.0.0" description="Production web application" | |
SHELL ["/bin/bash", "-c"]切换默认 shell | 高级 | SHELL ["/bin/bash", "-c"] |
文件操作(4)
| 命令 | 难度 | ||
|---|---|---|---|
COPY package.json package-lock.json ./复制具体文件,利用 Docker 缓存层 | 基础 | COPY package.json package-lock.json ./ | |
COPY src/ /app/src/复制整个目录到镜像 | 基础 | COPY src/ /app/src/ | |
COPY --chown=node:node config/ /app/config/复制文件并设置所有权 | 中级 | COPY --chown=node:node config/ /app/config/ | |
ADD app.tar.gz /opt/app/添加并自动解压 tar 包 | 中级 | ADD app.tar.gz /opt/app/ |
多阶段构建(2)
| 命令 | 难度 | ||
|---|---|---|---|
COPY --from=builder /app/dist /usr/share/nginx/html从多阶段构建的前一阶段复制产物 | 中级 | COPY --from=builder /app/dist /usr/share/nginx/html | |
# 多阶段构建示例多阶段构建:分离构建与运行环境 | 高级 | FROM golang:1.22 AS builder
WORKDIR /build
COPY . .
RUN go build -o app .
FROM alpine:3.20
COPY --from=builder /build/app /app
ENTRYPOINT ["/app"] |
启动配置(6)
| 命令 | 难度 | ||
|---|---|---|---|
EXPOSE 8080声明容器监听的端口(仅文档作用) | 基础 | EXPOSE 8080 | |
VOLUME ["/data"]声明匿名挂载卷 | 中级 | VOLUME ["/data"] | |
CMD ["node", "server.js"]提供默认执行命令(可被 docker run 覆盖) | 基础 | CMD ["node", "server.js"] | |
ENTRYPOINT ["nginx", "-g", "daemon off;"]设置容器入口点(不可覆盖,除非使用 --entrypoint) | 中级 | ENTRYPOINT ["nginx", "-g", "daemon off;"] | |
ENTRYPOINT ["python"]\nCMD ["app.py"]ENTRYPOINT 与 CMD 组合使用 | 中级 | ENTRYPOINT ["python"]\nCMD ["app.py"] | |
HEALTHCHECK --interval=30s --timeout=3s --retries=3 CMD curl -f http://localhost:8080/health || exit 1设置容器健康检查 | 高级 | HEALTHCHECK --interval=30s --timeout=3s --retries=3 CMD curl -f http://localhost:8080/health || exit 1 |
最佳实践(7)
| 命令 | 难度 | ||
|---|---|---|---|
RUN addgroup -S appgroup && adduser -S appuser -G appgroup\nUSER appuser创建非 root 用户并切换(安全最佳实践) | 中级 | RUN addgroup -S appgroup && adduser -S appuser -G appgroup\nUSER appuser | |
ONBUILD COPY . /app/src设置触发器指令,当此镜像被用作基础镜像时执行 | 高级 | ONBUILD COPY . /app/src | |
# .dockerignore 文件内容使用 .dockerignore 排除构建上下文中的无关文件 | 基础 | node_modules
.git
*.md
Dockerfile
.env | |
ENV TZ=Asia/Shanghai设置容器时区 | 基础 | ENV TZ=Asia/Shanghai\nRUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime | |
RUN apt-get install -y --no-install-recommends curl安装系统包时不安装推荐的依赖包 | 中级 | RUN apt-get install -y --no-install-recommends curl | |
# 按变更频率排序指令将不易变的指令放在前面以最大化缓存利用 | 中级 | FROM node:20-alpine
COPY package*.json ./
RUN npm install
COPY . . | |
FROM node:20.11-alpine3.19使用精确版本标签而非 latest | 基础 | FROM node:20.11-alpine3.19 |