← 返回首页

核心优势

📦
环境一致性

开发、测试、生产环境完全一致,彻底消除"在我机器上能跑"问题

🚀
快速部署

秒级启动容器,一键部署整套服务,支持快速回滚

🔄
资源隔离

容器间相互隔离,互不影响,安全可控,资源限制

📈
弹性伸缩

轻松扩展服务实例,应对流量变化,支持自动伸缩

💾
镜像复用

分层存储,镜像复用,节省磁盘空间和构建时间

🔧
易于维护

版本化管理,便于追踪变更,简化运维工作

核心概念

Docker 架构

Docker 核心组件
┌─────────────────────────────────────────────────────────────┐ │ Docker Client │ │ (docker CLI) │ └─────────────────────────┬───────────────────────────────────┘ │ REST API ┌─────────────────────────▼───────────────────────────────────┐ │ Docker Daemon │ │ (dockerd) │ ├─────────────────────────────────────────────────────────────┤ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ │ Images │ │ Containers │ │ Networks │ │ │ │ 镜像 │ │ 容器 │ │ 网络 │ │ │ └─────────────┘ └─────────────┘ └─────────────────────┘ │ │ ┌─────────────┐ ┌─────────────────────────────────────┐ │ │ │ Volumes │ │ Docker Registry │ │ │ │ 数据卷 │ │ (Docker Hub / 私有仓库) │ │ │ └─────────────┘ └─────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘

核心概念对比

概念 说明 类比
Image 只读模板,包含运行应用所需的所有内容 类 / 蓝图
Container 镜像的运行实例,可以启动、停止、删除 对象 / 实例
Dockerfile 构建镜像的脚本文件 配方 / 说明书
Volume 持久化存储,数据独立于容器生命周期 外接硬盘
Network 容器间通信的虚拟网络 局域网
Registry 存储和分发镜像的服务 应用商店

Dockerfile 编写

Node.js 应用 Dockerfile(多阶段构建)

多阶段构建可以显著减小最终镜像大小,提高安全性。

Dockerfile
# ============================================ # 阶段1: 依赖安装 # ============================================ FROM node:18-alpine AS deps WORKDIR /app # 只复制依赖文件,利用 Docker 缓存 COPY package.json package-lock.json ./ # 安装生产依赖 RUN npm ci --only=production && npm cache clean --force # ============================================ # 阶段2: 构建(如果需要编译) # ============================================ FROM node:18-alpine AS builder WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . # 如果有 TypeScript 或其他构建步骤 # RUN npm run build # ============================================ # 阶段3: 生产镜像 # ============================================ FROM node:18-alpine AS runner # 设置环境变量 ENV NODE_ENV=production ENV PORT=3000 WORKDIR /app # 创建非 root 用户(安全最佳实践) RUN addgroup --system --gid 1001 nodejs && \ adduser --system --uid 1001 appuser # 从依赖阶段复制 node_modules COPY --from=deps /app/node_modules ./node_modules # 从构建阶段复制应用代码 COPY --from=builder /app/src ./src COPY --from=builder /app/package.json ./ # 设置文件权限 RUN chown -R appuser:nodejs /app # 切换到非 root 用户 USER appuser # 暴露端口 EXPOSE 3000 # 健康检查 HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1 # 启动命令 CMD ["node", "src/app.js"]

Dockerfile 指令详解

指令 说明 示例
FROM 指定基础镜像 FROM node:18-alpine
WORKDIR 设置工作目录 WORKDIR /app
COPY 复制文件到镜像 COPY . .
RUN 执行命令(构建时) RUN npm install
ENV 设置环境变量 ENV NODE_ENV=production
EXPOSE 声明端口(文档作用) EXPOSE 3000
CMD 容器启动命令 CMD ["node", "app.js"]
ENTRYPOINT 容器入口点 ENTRYPOINT ["npm"]

.dockerignore 文件

.dockerignore
# 依赖目录 node_modules npm-debug.log # 版本控制 .git .gitignore # 开发配置 .env .env.* !.env.example # 测试和文档 tests *.md docs # Docker 相关 Dockerfile* docker-compose* .dockerignore # IDE 配置 .vscode .idea # 日志和临时文件 logs *.log tmp coverage
💡 最佳实践

使用 .dockerignore 排除不必要的文件,可以加快构建速度并减小镜像体积。

Docker Compose

完整的多服务编排配置

docker-compose.yml
version: '3.8' services: # ========================================== # Node.js 应用服务 # ========================================== app: build: context: . dockerfile: Dockerfile args: - NODE_ENV=production container_name: myapp-server restart: unless-stopped ports: - "3000:3000" environment: - NODE_ENV=production - PORT=3000 - MONGODB_URI=mongodb://admin:${MONGO_PASSWORD}@mongo:27017/myapp?authSource=admin - REDIS_URL=redis://redis:6379 depends_on: mongo: condition: service_healthy redis: condition: service_healthy networks: - app-network volumes: - ./logs:/app/logs deploy: resources: limits: cpus: '1' memory: 512M reservations: cpus: '0.5' memory: 256M # ========================================== # MongoDB 数据库 # ========================================== mongo: image: mongo:6 container_name: myapp-mongo restart: unless-stopped environment: - MONGO_INITDB_ROOT_USERNAME=admin - MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD} - MONGO_INITDB_DATABASE=myapp volumes: - mongo-data:/data/db - ./mongo-init:/docker-entrypoint-initdb.d:ro networks: - app-network healthcheck: test: echo 'db.runCommand("ping").ok' | mongosh localhost:27017/test --quiet interval: 10s timeout: 5s retries: 5 start_period: 30s # ========================================== # Redis 缓存 # ========================================== redis: image: redis:7-alpine container_name: myapp-redis restart: unless-stopped command: redis-server --appendonly yes --maxmemory 128mb --maxmemory-policy allkeys-lru volumes: - redis-data:/data networks: - app-network healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 # ========================================== # Nginx 反向代理 # ========================================== nginx: image: nginx:alpine container_name: myapp-nginx restart: unless-stopped ports: - "80:80" - "443:443" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/ssl:/etc/nginx/ssl:ro - ./public:/usr/share/nginx/html:ro depends_on: - app networks: - app-network # ========================================== # 数据卷 # ========================================== volumes: mongo-data: driver: local redis-data: driver: local # ========================================== # 网络 # ========================================== networks: app-network: driver: bridge ipam: config: - subnet: 172.20.0.0/16

开发环境配置

docker-compose.dev.yml
version: '3.8' services: app: build: context: . dockerfile: Dockerfile.dev volumes: # 挂载源码,实现热重载 - ./src:/app/src - ./package.json:/app/package.json # 排除 node_modules - /app/node_modules environment: - NODE_ENV=development - DEBUG=app:* command: npm run dev mongo: ports: # 开发时暴露端口,方便调试 - "27017:27017" redis: ports: - "6379:6379" # 使用方式: docker-compose -f docker-compose.yml -f docker-compose.dev.yml up

网络配置

Docker 网络类型

网络类型 说明 使用场景
bridge 默认网络,容器通过虚拟网桥通信 单机多容器
host 容器使用主机网络栈 高性能场景
none 禁用网络 安全隔离
overlay 跨主机容器通信 Docker Swarm

Nginx 反向代理配置

nginx/nginx.conf
events { worker_connections 1024; } http { # 上游服务器组 upstream app_servers { server app:3000; # 如果有多个实例 # server app2:3000; # server app3:3000; } # Gzip 压缩 gzip on; gzip_types text/plain application/json application/javascript text/css; server { listen 80; server_name localhost; # 静态文件 location /static/ { alias /usr/share/nginx/html/; expires 30d; add_header Cache-Control "public, immutable"; } # API 代理 location /api/ { proxy_pass http://app_servers; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_cache_bypass $http_upgrade; # 超时设置 proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; } # WebSocket 支持 location /ws/ { proxy_pass http://app_servers; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } } }

数据持久化

Volume 类型对比

类型 语法 特点 使用场景
命名卷 volume-name:/path Docker 管理,跨容器共享 数据库存储
绑定挂载 ./host:/container 直接映射主机目录 开发时代码同步
tmpfs tmpfs:/path 内存存储,容器停止即丢失 临时文件、敏感数据

数据备份与恢复

备份脚本 backup.sh
#!/bin/bash # 设置变量 BACKUP_DIR="/backups" DATE=$(date +%Y%m%d_%H%M%S) # 备份 MongoDB docker exec myapp-mongo mongodump \ --username admin \ --password $MONGO_PASSWORD \ --authenticationDatabase admin \ --out /backup # 复制到主机 docker cp myapp-mongo:/backup $BACKUP_DIR/mongo_$DATE # 备份 Volume docker run --rm \ -v mongo-data:/source:ro \ -v $BACKUP_DIR:/backup \ alpine tar czf /backup/mongo-data_$DATE.tar.gz -C /source . # 清理7天前的备份 find $BACKUP_DIR -type f -mtime +7 -delete echo "备份完成: $DATE"

常用命令

Docker 命令

命令 说明
docker build -t myapp . 构建镜像
docker run -d -p 3000:3000 myapp 运行容器
docker ps -a 查看所有容器
docker logs -f container_name 查看容器日志
docker exec -it container_name sh 进入容器
docker stop $(docker ps -q) 停止所有容器
docker system prune -a 清理未使用的资源

Docker Compose 命令

命令 说明
docker-compose up -d 后台启动所有服务
docker-compose down -v 停止并删除容器和卷
docker-compose logs -f app 查看指定服务日志
docker-compose ps 查看服务状态
docker-compose restart app 重启指定服务
docker-compose build --no-cache 重新构建镜像
docker-compose exec app sh 进入服务容器
docker-compose pull 拉取最新镜像

生产环境部署

生产环境检查清单

  • 使用非 root 用户 - 在 Dockerfile 中创建并切换到普通用户
  • 设置资源限制 - 限制 CPU 和内存使用,防止单个容器耗尽资源
  • 配置健康检查 - 让编排系统能够检测和重启不健康的容器
  • 使用多阶段构建 - 减小镜像体积,提高安全性
  • 固定镜像版本 - 避免使用 latest 标签,确保可重复构建
  • 配置日志驱动 - 使用集中式日志收集
  • 启用重启策略 - 设置 restart: unless-stopped
  • 使用 secrets 管理敏感信息 - 不要在镜像中硬编码密码

CI/CD 集成示例

.github/workflows/deploy.yml
name: Deploy on: push: branches: [main] jobs: build-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and push uses: docker/build-push-action@v4 with: context: . push: true tags: | username/myapp:latest username/myapp:${{ github.sha }} - name: Deploy to server uses: appleboy/ssh-action@master with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USER }} key: ${{ secrets.SSH_PRIVATE_KEY }} script: | cd /app docker-compose pull docker-compose up -d docker system prune -f
⚠️ 安全提醒

生产环境中,敏感信息(如数据库密码)应该使用环境变量或 Docker Secrets 管理,不要写在配置文件中。