Dockerfile编写:最佳实践
Dockerfile编写:最佳实践
Dockerfile指令详解
FROM指令
# 指定基础镜像
FROM ubuntu:22.04
# 使用构建参数
ARG BASE_IMAGE=ubuntu:22.04
FROM ${BASE_IMAGE}
# 多平台构建
FROM --platform=linux/amd64 ubuntu:22.04
RUN指令
# 使用shell格式
RUN apt-get update && apt-get install -y curl
# 使用exec格式(推荐)
RUN ["apt-get", "update"]
RUN ["apt-get", "install", "-y", "curl"]
# 合并RUN减少层数
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
git \
vim && \
rm -rf /var/lib/apt/lists/*
COPY与ADD
# COPY(推荐)
COPY package.json /app/
COPY --chown=node:node . /app/
# ADD(自动解压tar,慎用)
ADD app.tar.gz /app/
# 从URL复制
ADD https://example.com/file.tar.gz /tmp/
CMD与ENTRYPOINT
# CMD:容器启动时的默认命令(可被覆盖)
CMD ["python3", "app.py"]
CMD python3 app.py
# ENTRYPOINT:容器启动时的入口(不易被覆盖)
ENTRYPOINT ["python3"]
CMD ["app.py"]
# exec格式(推荐)
ENTRYPOINT ["python3"]
CMD ["app.py"]
多阶段构建
Go应用示例
# 构建阶段
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /app/server .
# 运行阶段
FROM alpine:latest
RUN apk --no-cache add ca-certificates tzdata
WORKDIR /app
COPY --from=builder /app/server .
EXPOSE 8080
CMD ["./server"]
Node.js应用示例
# 构建阶段
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# 运行阶段
FROM node:18-alpine
RUN addgroup -g 1001 -S appgroup && \
adduser -S appuser -u 1001 -G appgroup
WORKDIR /app
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:appgroup /app/package.json .
USER appuser
EXPOSE 3000
CMD ["node", "dist/index.js"]
安全最佳实践
使用非root用户
# 创建专用用户
RUN groupadd -r appgroup && useradd -r -g appgroup appuser
# 切换用户
USER appuser
# 或者在COPY时设置所有权
COPY --chown=appuser:appgroup . /app
扫描和最小化
# 使用最小基础镜像
FROM alpine:3.18
# 只安装必要的包
RUN apk --no-cache add \
ca-certificates \
curl \
&& rm -rf /var/cache/apk/*
# 不安装文档和缓存
RUN apt-get install -y --no-install-recommends \
--no-install-suggests \
package-name
使用.dockerignore
# .dockerignore文件
.git
.gitignore
.dockerignore
Dockerfile
docker-compose*.yml
README.md
.env
.env.*
node_modules
__pycache__
*.pyc
*.pyo
.vscode
.idea
构建缓存优化
缓存层顺序
# 依赖层(变化少,放前面)
COPY package.json package-lock.json ./
RUN npm ci --only=production
# 源代码层(变化多,放后面)
COPY . .
使用BuildKit
# 启用BuildKit
export DOCKER_BUILDKIT=1
# 构建时指定缓存
docker build --cache-from myapp:latest -t myapp:new .
# 并行构建
docker buildx build --parallel .
高级技巧
使用ARG和ENV
# ARG:构建时变量
ARG NODE_VERSION=18
FROM node:${NODE_VERSION}-alpine
# ENV:运行时变量
ENV NODE_ENV=production
ENV APP_PORT=3000
# 使用多阶段ARG
ARG VERSION=latest
FROM node:${VERSION}-alpine AS builder
# ...构建过程...
FROM node:${VERSION}-alpine
# ...运行配置...
使用HEALTHCHECK
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
使用LABEL
LABEL maintainer="devops@example.com"
LABEL version="1.0"
LABEL description="Production web application"
LABEL org.opencontainers.image.source="https://github.com/example/app"
多平台构建
# 创建构建器实例
docker buildx create --name mybuilder --use
# 构建多平台镜像
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t myapp:latest \
--push \
.
镜像大小对比
| 基础镜像 | 大小 | 适用场景 |
|---|---|---|
| scratch | 0MB | 静态二进制 |
| alpine | ~5MB | 通用 |
| debian:slim | ~80MB | 需要glibc |
| ubuntu:22.04 | ~77MB | 开发环境 |
总结
编写高质量的Dockerfile需要遵循最佳实践:使用多阶段构建、最小化镜像体积、确保安全性、优化构建缓存。这些技巧将帮助你构建出高效、安全的生产级容器镜像。