前言
Docker已成为现代应用部署的标准方式。本文总结在生产环境中使用Docker的最佳实践,涵盖镜像构建、容器编排、安全加固和性能优化等方面。
一、Dockerfile最佳实践
1.1 多阶段构建
多阶段构建可以显著减小最终镜像的体积,同时保证构建环境完整:
# 构建阶段
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# 运行阶段
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 3000
CMD ["node", "dist/main.js"]
1.2 利用构建缓存
合理安排Dockerfile中指令的顺序,将变化频率低的内容放在前面,充分利用Docker的层缓存机制:
- 先复制依赖文件(package.json),安装依赖
- 再复制源代码,构建应用
- 这样修改代码时不需要重新安装依赖
二、容器安全加固
2.1 非root用户运行
生产环境中应避免以root身份运行容器:
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
2.2 只读文件系统
将容器根文件系统设为只读,只挂载必要的可写目录:
docker run --read-only \
--tmpfs /tmp \
-v /data:/app/data \
myapp:latest
2.3 资源限制
始终为容器设置CPU和内存限制,防止单个容器耗尽宿主机资源:
docker run \
--memory="512m" \
--memory-swap="1g" \
--cpus="1.0" \
myapp:latest
三、Docker Compose编排
对于多容器应用,使用Docker Compose管理容器间的依赖关系:
version: '3.8'
services:
api:
build: ./api
ports:
- "3000:3000"
depends_on:
mysql:
condition: service_healthy
environment:
- DB_HOST=mysql
- DB_PORT=3306
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: myapp
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
volumes:
mysql_data:
四、日志与监控
容器的标准输出(stdout/stderr)是最简单的日志收集方式。配合Docker的日志驱动,可以将日志转发到集中式日志系统:
- json-file:默认驱动,适合开发环境
- syslog:转发到syslog服务器
- fluentd:对接Fluentd日志收集
- 建议使用结构化日志(JSON格式),便于后续分析
五、总结
Docker容器化部署的关键原则:
- 镜像尽可能小,使用Alpine基础镜像
- 容器以非root用户运行
- 始终设置资源限制
- 使用健康检查确保服务可用
- 日志输出到stdout,外部收集
- 敏感信息通过环境变量或Secret注入,不写入镜像
以上实践来自实际生产环境的经验总结,建议根据具体业务场景灵活调整。