- 发布于
Docker 容器化实践:从入门到生产部署
- 作者

- 姓名
- 全能波
- GitHub
- @weicracker
Docker 容器化实践:从入门到生产部署
Docker 已经成为现代应用部署的标准工具。本文将深入探讨 Docker 的核心概念、最佳实践和生产环境部署策略。
Docker 基础概念
什么是 Docker?
Docker 是一个开源的容器化平台,它允许开发者将应用程序及其依赖项打包到轻量级、可移植的容器中。
# 基础 Dockerfile 示例
FROM node:16-alpine
# 设置工作目录
WORKDIR /app
# 复制 package.json 和 package-lock.json
COPY package*.json ./
# 安装依赖
RUN npm ci --only=production
# 复制应用代码
COPY . .
# 暴露端口
EXPOSE 3000
# 启动应用
CMD ["npm", "start"]
核心概念解释
# 镜像(Image)- 只读模板
docker images
# 容器(Container)- 镜像的运行实例
docker ps
# Dockerfile - 构建镜像的指令文件
docker build -t myapp:latest .
# 仓库(Registry)- 存储镜像的地方
docker push myapp:latest
docker pull nginx:alpine
Dockerfile 最佳实践
1. 多阶段构建
# 多阶段构建 - 前端应用
FROM node:16-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:alpine
# 复制构建产物
COPY /app/dist /usr/share/nginx/html
# 复制 nginx 配置
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
2. 优化镜像大小
# Node.js 应用优化
FROM node:16-alpine
# 创建非 root 用户
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
WORKDIR /app
# 只复制必要的文件
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
# 复制应用代码
COPY . .
# 切换到非 root 用户
USER nextjs
EXPOSE 3000
# 使用 exec 形式的 CMD
CMD ["node", "server.js"]
3. 缓存优化
# 利用 Docker 缓存层
FROM python:3.9-slim
WORKDIR /app
# 先复制依赖文件(变化较少)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 再复制应用代码(变化较多)
COPY . .
# 设置环境变量
ENV PYTHONPATH=/app
ENV FLASK_APP=app.py
EXPOSE 5000
CMD ["flask", "run", "--host=0.0.0.0"]
Docker Compose 编排
1. 基础服务编排
# docker-compose.yml
version: '3.8'
services:
# Web 应用
web:
build: .
ports:
- '3000:3000'
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://user:password@db:5432/myapp
depends_on:
- db
- redis
volumes:
- ./uploads:/app/uploads
restart: unless-stopped
# 数据库
db:
image: postgres:13-alpine
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
restart: unless-stopped
# Redis 缓存
redis:
image: redis:6-alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
restart: unless-stopped
# Nginx 反向代理
nginx:
image: nginx:alpine
ports:
- '80:80'
- '443:443'
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- web
restart: unless-stopped
volumes:
postgres_data:
redis_data:
2. 开发环境配置
# docker-compose.dev.yml
version: '3.8'
services:
web:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- '3000:3000'
environment:
- NODE_ENV=development
volumes:
- .:/app
- /app/node_modules
command: npm run dev
db:
ports:
- '5432:5432'
environment:
POSTGRES_DB: myapp_dev
# 开发工具
adminer:
image: adminer
ports:
- '8080:8080'
depends_on:
- db
3. 生产环境配置
# docker-compose.prod.yml
version: '3.8'
services:
web:
image: myapp:latest
deploy:
replicas: 3
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
environment:
- NODE_ENV=production
secrets:
- db_password
- jwt_secret
db:
image: postgres:13-alpine
deploy:
replicas: 1
placement:
constraints:
- node.role == manager
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
external: true
jwt_secret:
external: true
容器网络和存储
1. 网络配置
# 自定义网络
version: '3.8'
services:
web:
networks:
- frontend
- backend
db:
networks:
- backend
nginx:
networks:
- frontend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # 内部网络,不能访问外网
# Docker 网络命令
docker network create --driver bridge mynetwork
docker network ls
docker network inspect mynetwork
# 连接容器到网络
docker network connect mynetwork mycontainer
2. 数据持久化
# 数据卷配置
version: '3.8'
services:
db:
image: postgres:13
volumes:
# 命名卷
- postgres_data:/var/lib/postgresql/data
# 绑定挂载
- ./backups:/backups
# 临时文件系统
- type: tmpfs
target: /tmp
tmpfs:
size: 100M
volumes:
postgres_data:
driver: local
driver_opts:
type: none
o: bind
device: /data/postgres
监控和日志
1. 健康检查
# Dockerfile 中的健康检查
FROM node:16-alpine
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000
# 健康检查
HEALTHCHECK \
CMD curl -f http://localhost:3000/health || exit 1
CMD ["npm", "start"]
# docker-compose.yml 中的健康检查
version: '3.8'
services:
web:
build: .
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost:3000/health']
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
2. 日志管理
# 日志配置
version: '3.8'
services:
web:
image: myapp:latest
logging:
driver: 'json-file'
options:
max-size: '10m'
max-file: '3'
# 使用 ELK 栈
elasticsearch:
image: elasticsearch:7.14.0
environment:
- discovery.type=single-node
volumes:
- elasticsearch_data:/usr/share/elasticsearch/data
logstash:
image: logstash:7.14.0
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
kibana:
image: kibana:7.14.0
ports:
- '5601:5601'
depends_on:
- elasticsearch
volumes:
elasticsearch_data:
3. 监控配置
# Prometheus + Grafana 监控
version: '3.8'
services:
prometheus:
image: prom/prometheus
ports:
- '9090:9090'
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
grafana:
image: grafana/grafana
ports:
- '3001:3000'
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana_data:/var/lib/grafana
node-exporter:
image: prom/node-exporter
ports:
- '9100:9100'
volumes:
prometheus_data:
grafana_data:
安全最佳实践
1. 镜像安全
# 安全的 Dockerfile
FROM node:16-alpine
# 更新系统包
RUN apk update && apk upgrade
# 创建非 root 用户
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001 -G nodejs
WORKDIR /app
# 设置正确的文件权限
COPY package*.json ./
RUN npm ci --only=production
COPY . .
# 切换到非 root 用户
USER nextjs
# 只暴露必要的端口
EXPOSE 3000
CMD ["node", "server.js"]
2. 运行时安全
# 安全的 docker-compose 配置
version: '3.8'
services:
web:
image: myapp:latest
# 只读根文件系统
read_only: true
# 临时文件系统
tmpfs:
- /tmp
- /var/run
# 安全选项
security_opt:
- no-new-privileges:true
# 资源限制
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
# 用户命名空间
user: '1001:1001'
3. 密钥管理
# Docker Secrets
echo "mysecretpassword" | docker secret create db_password -
# 在 swarm 模式下使用
docker service create \
--name myapp \
--secret db_password \
myapp:latest
生产部署策略
1. Docker Swarm 部署
# 初始化 Swarm
docker swarm init
# 部署服务栈
docker stack deploy -c docker-compose.prod.yml myapp
# 扩展服务
docker service scale myapp_web=5
# 滚动更新
docker service update --image myapp:v2 myapp_web
2. CI/CD 集成
# GitHub Actions 示例
name: Build and Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build Docker image
run: |
docker build -t myapp:${{ github.sha }} .
docker tag myapp:${{ github.sha }} myapp:latest
- name: Push to registry
run: |
echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
docker push myapp:${{ github.sha }}
docker push myapp:latest
- name: Deploy to production
run: |
docker stack deploy -c docker-compose.prod.yml myapp
3. 蓝绿部署
#!/bin/bash
# 蓝绿部署脚本
CURRENT_COLOR=$(docker service ls --filter name=myapp --format "{{.Name}}" | grep -o "blue\|green")
NEW_COLOR="blue"
if [ "$CURRENT_COLOR" = "blue" ]; then
NEW_COLOR="green"
fi
echo "当前环境: $CURRENT_COLOR"
echo "部署到: $NEW_COLOR"
# 部署新版本
docker service create \
--name myapp-$NEW_COLOR \
--replicas 3 \
--network myapp-network \
myapp:latest
# 等待服务就绪
sleep 30
# 健康检查
if curl -f http://myapp-$NEW_COLOR:3000/health; then
echo "新版本健康检查通过"
# 切换流量
docker service update --label-add version=$NEW_COLOR nginx
# 移除旧版本
docker service rm myapp-$CURRENT_COLOR
echo "部署完成"
else
echo "健康检查失败,回滚"
docker service rm myapp-$NEW_COLOR
exit 1
fi
性能优化
1. 镜像优化
# 优化的多阶段构建
FROM node:16-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:16-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:16-alpine AS runner
WORKDIR /app
ENV NODE_ENV production
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
COPY /app/node_modules ./node_modules
COPY /app/dist ./dist
USER nextjs
EXPOSE 3000
CMD ["node", "dist/server.js"]
2. 资源限制
# 资源限制和预留
version: '3.8'
services:
web:
image: myapp:latest
deploy:
resources:
limits:
cpus: '1.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
故障排查
1. 常用调试命令
# 查看容器日志
docker logs -f container_name
# 进入容器
docker exec -it container_name /bin/sh
# 查看容器资源使用
docker stats
# 检查容器详细信息
docker inspect container_name
# 查看容器进程
docker top container_name
2. 性能分析
# 容器性能监控
docker run --rm -it \
--pid container:myapp \
--cap-add SYS_PTRACE \
nicolaka/netshoot
# 网络调试
docker run --rm -it \
--net container:myapp \
nicolaka/netshoot
总结
Docker 容器化为现代应用部署提供了强大的能力:
- 环境一致性:开发、测试、生产环境完全一致
- 快速部署:秒级启动和扩展
- 资源隔离:安全的多租户环境
- 微服务架构:完美支持微服务部署
- DevOps 集成:与 CI/CD 流水线无缝集成
掌握 Docker,你就能构建出高效、可靠的现代应用部署方案!
Docker 是现代应用部署的基础设施,值得深入学习和实践。