Docker 容器化实践
🎯 概述
Docker 是一个开源的容器化平台,能够将应用程序及其依赖项打包到轻量级、可移植的容器中。本文将分享Docker在实际项目中的使用经验和最佳实践。
📚 基础概念
容器 vs 虚拟机
┌─────────────────────────────────────┐
│ 虚拟机架构 │
├─────────────────────────────────────┤
│ App1 │ App2 │ App3 │ App4 │
├─────────────────────────────────────┤
│ Guest OS │ Guest OS │ Guest OS │
├─────────────────────────────────────┤
│ Hypervisor │
├─────────────────────────────────────┤
│ Host OS │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ 容器架构 │
├─────────────────────────────────────┤
│ App1 │ App2 │ App3 │ App4 │
├─────────────────────────────────────┤
│ Docker Engine │
├─────────────────────────────────────┤
│ Host OS │
└─────────────────────────────────────┘核心组件
- 镜像 (Image): 只读的模板,用于创建容器
- 容器 (Container): 镜像的运行实例
- 仓库 (Repository): 存储镜像的地方
- Dockerfile: 用于构建镜像的文本文件
🛠️ 实践应用
1. 基础Dockerfile
dockerfile
# 多阶段构建示例
FROM node:18-alpine AS builder
# 设置工作目录
WORKDIR /app
# 复制package文件
COPY package*.json ./
# 安装依赖
RUN npm ci --only=production
# 复制源代码
COPY . .
# 构建应用
RUN npm run build
# 生产阶段
FROM node:18-alpine AS production
# 创建非root用户
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# 设置工作目录
WORKDIR /app
# 复制构建产物
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
# 切换到非root用户
USER nextjs
# 暴露端口
EXPOSE 3000
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# 启动命令
CMD ["npm", "start"]2. 微服务架构
yaml
# docker-compose.yml
version: '3.8'
services:
# API网关
api-gateway:
build: ./api-gateway
ports:
- "8080:8080"
environment:
- NODE_ENV=production
- REDIS_URL=redis://redis:6379
depends_on:
- redis
- user-service
- order-service
networks:
- app-network
# 用户服务
user-service:
build: ./user-service
environment:
- NODE_ENV=production
- DB_HOST=mysql
- DB_PORT=3306
- DB_NAME=user_db
- DB_USER=root
- DB_PASSWORD=password
depends_on:
- mysql
networks:
- app-network
# 订单服务
order-service:
build: ./order-service
environment:
- NODE_ENV=production
- DB_HOST=mysql
- DB_PORT=3306
- DB_NAME=order_db
- DB_USER=root
- DB_PASSWORD=password
depends_on:
- mysql
networks:
- app-network
# 数据库
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: app_db
volumes:
- mysql_data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
ports:
- "3306:3306"
networks:
- app-network
# Redis缓存
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- app-network
# Nginx负载均衡
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- api-gateway
networks:
- app-network
volumes:
mysql_data:
redis_data:
networks:
app-network:
driver: bridge3. 开发环境配置
yaml
# docker-compose.dev.yml
version: '3.8'
services:
# 开发服务器
app-dev:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
- "9229:9229" # Node.js调试端口
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
- DEBUG=app:*
command: npm run dev
networks:
- dev-network
# 开发数据库
mysql-dev:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: dev_password
MYSQL_DATABASE: dev_db
ports:
- "3307:3306"
volumes:
- mysql_dev_data:/var/lib/mysql
networks:
- dev-network
# 开发Redis
redis-dev:
image: redis:7-alpine
ports:
- "6380:6379"
networks:
- dev-network
volumes:
mysql_dev_data:
networks:
dev-network:
driver: bridge🚀 高级技巧
1. 多阶段构建优化
dockerfile
# 前端应用多阶段构建
FROM node:18-alpine AS dependencies
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine AS production
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]2. 健康检查配置
dockerfile
# 健康检查示例
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# 或者使用自定义脚本
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD ./health-check.shbash
#!/bin/bash
# health-check.sh
set -e
# 检查应用是否响应
curl -f http://localhost:3000/health || exit 1
# 检查数据库连接
node -e "
const mysql = require('mysql2/promise');
mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME
}).then(() => process.exit(0))
.catch(() => process.exit(1));
"3. 安全配置
dockerfile
# 安全最佳实践
FROM node:18-alpine
# 创建非root用户
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001
# 设置工作目录
WORKDIR /app
# 复制文件并设置权限
COPY --chown=nextjs:nodejs package*.json ./
RUN npm ci --only=production && npm cache clean --force
COPY --chown=nextjs:nodejs . .
# 切换到非root用户
USER nextjs
# 设置文件权限
RUN chmod -R 755 /app
# 暴露端口
EXPOSE 3000
# 启动应用
CMD ["npm", "start"]🔧 监控和日志
1. 日志配置
yaml
# docker-compose.yml 日志配置
services:
app:
build: .
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
labels:
- "com.example.service=app"
- "com.example.version=1.0.0"2. 监控配置
yaml
# 监控服务
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
grafana:
image: grafana/grafana
ports:
- "3001:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana_data:/var/lib/grafana📦 部署策略
1. 蓝绿部署
bash
#!/bin/bash
# blue-green-deploy.sh
# 当前运行的是蓝色环境
CURRENT_COLOR="blue"
NEW_COLOR="green"
# 启动绿色环境
docker-compose -f docker-compose.${NEW_COLOR}.yml up -d
# 等待绿色环境就绪
echo "等待绿色环境启动..."
sleep 30
# 健康检查
if curl -f http://localhost:3001/health; then
echo "绿色环境健康检查通过"
# 切换流量到绿色环境
docker-compose -f docker-compose.nginx.yml up -d
# 停止蓝色环境
docker-compose -f docker-compose.${CURRENT_COLOR}.yml down
echo "部署完成,当前环境:${NEW_COLOR}"
else
echo "绿色环境健康检查失败,回滚到蓝色环境"
docker-compose -f docker-compose.${NEW_COLOR}.yml down
exit 1
fi2. 滚动更新
yaml
# docker-compose.rolling.yml
version: '3.8'
services:
app:
image: myapp:latest
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
order: start-first
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3🎯 最佳实践
1. 镜像优化
- 使用多阶段构建减少镜像大小
- 选择合适的基础镜像
- 清理不必要的文件和缓存
- 使用.dockerignore文件
2. 容器编排
- 合理设置资源限制
- 使用健康检查
- 配置重启策略
- 实现优雅关闭
3. 安全考虑
- 使用非root用户运行容器
- 定期更新基础镜像
- 扫描镜像漏洞
- 限制容器权限
4. 监控和日志
- 集中化日志管理
- 设置监控告警
- 定期备份数据
- 性能指标收集
Docker让部署更简单! 🐳