Docker 容器化最佳实践
Docker 已成为现代软件开发和部署的标准工具。本文总结了使用 Docker 时的最佳实践,帮助你构建更安全、高效的容器化应用。
1. Dockerfile 优化
使用多阶段构建
# 构建阶段
FROM node:16-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# 生产阶段
FROM node:16-alpine
RUN apk add --no-cache dumb-init
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
USER node
EXPOSE 3000
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "server.js"]
层缓存优化
FROM ubuntu:20.04
# 先复制依赖文件,利用缓存
COPY requirements.txt .
RUN pip install -r requirements.txt
# 再复制源代码
COPY . .
2. 安全最佳实践
非 root 用户运行
FROM node:16-alpine
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
USER nextjs
最小化攻击面
FROM alpine:latest
RUN apk add --no-cache ca-certificates
COPY myapp /myapp
USER nobody
ENTRYPOINT ["/myapp"]
扫描镜像漏洞
# 使用 Trivy 扫描
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasecurity/trivy:latest image myimage:latest
# 使用 Clair
docker run --rm -p 6060:6060 quay.io/coreos/clair:latest
3. 镜像大小优化
使用 .dockerignore
node_modules
npm-debug.log
.git
.gitignore
README.md
.env
.nyc_output
coverage
链式 RUN 命令
RUN apt-get update && apt-get install -y \
package1 \
package2 \
package3 \
&& rm -rf /var/lib/apt/lists/*
使用 distroless 镜像
FROM golang:1.17 AS build
WORKDIR /go/src/app
COPY . .
RUN go build -o myapp .
FROM gcr.io/distroless/base
COPY --from=build /go/src/app/myapp /
CMD ["/myapp"]
4. 容器编排
Docker Compose 配置
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
depends_on:
- db
networks:
- webnet
db:
image: postgres:13
environment:
- POSTGRES_PASSWORD=mysecretpassword
volumes:
- db-data:/var/lib/postgresql/data
networks:
- webnet
volumes:
db-data:
networks:
webnet:
健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
5. 开发环境优化
开发用 Dockerfile
FROM node:16-alpine
# 安装开发依赖
RUN apk add --no-cache git
# 设置工作目录
WORKDIR /app
# 复制 package.json 并安装依赖
COPY package*.json ./
RUN npm install
# 复制源代码
COPY . .
# 暴露端口
EXPOSE 3000
# 启动命令
CMD ["npm", "run", "dev"]
使用 bind mounts 进行热重载
docker run -v $(pwd):/app -p 3000:3000 myapp
6. 性能优化
资源限制
services:
web:
deploy:
resources:
limits:
cpus: '0.50'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
使用合适的基础镜像
# 选择合适的基础镜像
FROM python:3.9-slim # 而不是 python:3.9
# 或者使用 Alpine
FROM python:3.9-alpine
7. 日志管理
结构化日志
// 使用 JSON 格式日志
console.log(JSON.stringify({
level: 'info',
message: 'User logged in',
userId: user.id,
timestamp: new Date().toISOString()
}));
日志轮转
# 使用 logrotate
RUN apt-get update && apt-get install -y logrotate
COPY logrotate.conf /etc/logrotate.d/app
8. 数据持久化
命名卷
services:
db:
image: postgres:13
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
备份策略
# 备份卷
docker run --rm -v postgres_data:/data -v $(pwd):/backup \
alpine tar czf /backup/backup.tar.gz -C /data .
9. 网络配置
使用用户定义网络
networks:
mynetwork:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
端口映射策略
# 开发环境
ports:
- "3000:3000"
# 生产环境(使用反向代理)
# 不暴露端口,直接通过网络连接
10. CI/CD 集成
多阶段构建在 CI/CD 中的应用
stages:
- build
- test
- deploy
build:
stage: build
script:
- docker build --target builder -t myapp:build .
- docker build --target production -t myapp:latest .
test:
stage: test
script:
- docker run myapp:latest npm test
deploy:
stage: deploy
script:
- docker push myapp:latest
总结
Docker 容器化带来了诸多好处,但要充分发挥其潜力需要遵循最佳实践:
- 安全第一:使用非 root 用户、最小化镜像
- 性能优化:多阶段构建、层缓存、资源限制
- 可维护性:结构化日志、健康检查、文档化
- 开发体验:热重载、开发环境优化
- 生产就绪:编排、监控、备份策略
通过这些实践,你可以构建出更安全、更高效、更易维护的容器化应用。
#docker #container #devops #best-practices