Dockerfile 最佳实践
目录
一个写得好的 Dockerfile 能显著减小镜像体积、加快构建速度、提升安全性。本文总结日常工作中最实用的 Dockerfile 编写规范。
1. 使用多阶段构建 (Multi-stage Build)
将编译环境和运行环境分离,最终镜像只包含运行所需的产物:
# 编译阶段
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o server .
# 运行阶段
FROM alpine:3.19
RUN apk add --no-cache ca-certificates
COPY --from=builder /app/server /usr/local/bin/
EXPOSE 8080
ENTRYPOINT ["server"]效果:Go 编译镜像 ~1GB → 最终镜像 ~20MB。
2. 选择合适的基础镜像
| 场景 | 推荐镜像 | 大小 |
|---|---|---|
| 通用 | alpine:3.19 |
~7MB |
| 静态二进制 | scratch / gcr.io/distroless/static |
0~2MB |
| Debian 需求 | debian:bookworm-slim |
~80MB |
| Python | python:3.12-slim |
~150MB |
避免使用
latest标签,始终锁定具体版本以保证构建可复现。
3. 合理利用构建缓存
Docker 按层缓存,变化频率低的指令放前面:
FROM node:20-alpine
WORKDIR /app
# 先复制依赖文件(变化少)
COPY package.json package-lock.json ./
RUN npm ci --production
# 再复制源码(变化频繁)
COPY . .
RUN npm run build如果先 COPY . . 再 npm install,每次代码改动都会重新安装依赖。
4. 减少镜像层数和体积
# ❌ 多个 RUN 产生多层
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
# ✅ 合并为一层,并清理缓存
RUN apt-get update && \
apt-get install -y --no-install-recommends curl && \
rm -rf /var/lib/apt/lists/*关键点:
--no-install-recommends避免安装不必要的包- 同一层内清理缓存,否则删除操作不会减小镜像体积
5. 不要以 root 运行
RUN addgroup -S app && adduser -S app -G app
USER app以非 root 用户运行容器,降低容器逃逸后的攻击面。
6. 使用 .dockerignore
在项目根目录创建 .dockerignore,避免将无关文件发送到构建上下文:
.git
node_modules
*.md
.env
.DS_Store
dist
coverage构建上下文越小,docker build 启动越快。
7. COPY vs ADD
# ✅ 优先使用 COPY(行为明确)
COPY app.tar.gz /app/
# ⚠️ ADD 会自动解压 tar 并支持 URL,行为隐式
ADD app.tar.gz /app/只在需要自动解压 tar 时使用 ADD,其他场景一律用 COPY。
8. ENTRYPOINT vs CMD
# ENTRYPOINT 定义容器的主进程
# CMD 提供默认参数,可被 docker run 覆盖
ENTRYPOINT ["python", "app.py"]
CMD ["--port", "8080"]# 使用默认参数
docker run myapp
# 等价于: python app.py --port 8080
# 覆盖参数
docker run myapp --port 9090
# 等价于: python app.py --port 9090始终使用 exec 格式
["executable", "param"],避免 shell 格式导致信号无法正确传递。
9. 健康检查
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -qO- http://localhost:8080/health || exit 1配合编排工具(Docker Compose / Kubernetes)实现自动重启不健康的容器。
10. 安全扫描
构建完成后扫描镜像漏洞:
# Trivy
trivy image myapp:latest
# Docker Scout
docker scout cves myapp:latest建议集成到 CI/CD Pipeline 中,阻断含高危漏洞的镜像发布。