Docker最佳实践
多阶段构建(Go示例)
# Stage 1: Build FROM golang:1.22-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download # Cache dependencies as separate layer COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o server . # Stage 2: Minimal runtime image FROM gcr.io/distroless/static-debian12 # Or: FROM alpine:3.19 (adds 5MB but has shell) COPY --from=builder /app/server /server EXPOSE 8080 ENTRYPOINT ["/server"]
层缓存优化
# BAD — invalidates cache on any source change COPY . . RUN npm install # GOOD — package.json changes rarely COPY package.json package-lock.json ./ RUN npm ci --only=production COPY . . # Rule: put things that change least first
安全加固
# Run as non-root user RUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser # Read-only filesystem docker run --read-only --tmpfs /tmp myapp # Limit capabilities docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp # Scan for vulnerabilities docker scout cves myimage:latest trivy image myimage:latest
docker-compose最佳实践
services:
app:
build:
context: .
target: production # Use build target
image: myapp:${VERSION:-latest}
restart: unless-stopped
environment:
- NODE_ENV=production
env_file: .env # Never hardcode secrets
ports:
- "127.0.0.1:8080:8080" # Bind to loopback only
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
deploy:
resources:
limits:
memory: 512m
cpus: '0.5'
镜像大小对比
| 基础镜像 | 大小 | Shell | 使用场景 |
|---|---|---|---|
| ubuntu:22.04 | ~77MB | ✓ | 完整调试 |
| debian:slim | ~74MB | ✓ | 精简Debian |
| alpine:3.19 | ~7MB | sh | 小,musl libc |
| distroless/static | ~2MB | ✗ | 静态编译二进制 |
| scratch | 0MB | ✗ | 最小,Go/Rust |