零度AI
高级22 分钟阅读

Claude Code Docker容器化

使用 Claude Code 编写 Dockerfile、docker-compose,实现应用的容器化部署

Claude CodeDocker容器化部署DevOps

Docker 容器化概述

Docker 是现代应用部署的标准方式。Claude Code 可以帮你快速编写 Dockerfile 和 docker-compose 配置。

前置条件

你需要先安装 Docker Desktop(Windows/Mac)或 Docker Engine(Linux)。

Dockerfile 编写

Node.js 应用 Dockerfile

bash
帮我为一个 Node.js + Express 应用创建一个优化过的 Dockerfile。
要求:
- 使用多阶段构建
- 生产环境使用非 root 用户
- 减小镜像体积
- 利用缓存优化构建速度
dockerfile
# 构建阶段
FROM node:20-alpine AS builder

WORKDIR /app

# 先复制 package 文件,利用 Docker 缓存
COPY package*.json ./
RUN npm ci --only=production

# 复制源代码并构建
COPY . .
RUN npm run build

# 生产阶段
FROM node:20-alpine AS production

# 创建非 root 用户
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nodeapp -u 1001

WORKDIR /app

# 复制 package 文件
COPY package*.json ./

# 只安装生产依赖
RUN npm ci --only=production && npm cache clean --force

# 从构建阶段复制构建产物
COPY --from=builder /app/dist ./dist

# 设置环境变量
ENV NODE_ENV=production
ENV PORT=3000

# 改变文件所有权
RUN chown -R nodeapp:nodejs /app

# 切换到非 root 用户
USER nodeapp

# 暴露端口
EXPOSE 3000

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD wget --quiet --tries=1 --spider http://localhost:3000/health || exit 1

# 启动命令
CMD ["node", "dist/server.js"]

React 前端 Dockerfile

dockerfile
# 构建阶段
FROM node:20-alpine AS builder

WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .
RUN npm run build

# 生产阶段 - 使用 Nginx
FROM nginx:alpine AS production

# 复制构建产物
COPY --from=builder /app/.next/static ./static
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/server ./server

# Nginx 配置
COPY nginx.conf /etc/nginx/nginx.conf

EXPOSE 80

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD wget --quiet --tries=1 --spider http://localhost/health || exit 1

CMD ["nginx", "-g", "daemon off;"]

Nginx 配置文件

nginx
# nginx.conf
events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # 日志格式
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/log/nginx/access.log main;
    error_log /var/log/nginx/error.log warn;

    # Gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

    # 限流
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

    server {
        listen 80;
        server_name localhost;
        root /usr/share/nginx/html;
        index index.html;

        # Next.js 静态文件
        location /_next/static {
            alias /app/static;
            expires 1y;
            add_header Cache-Control "public, immutable";
        }

        # API 代理
        location /api {
            limit_req zone=api burst=20 nodelay;
            proxy_pass http://backend:3000;
            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;
        }

        # 健康检查
        location /health {
            access_log off;
            return 200 'OK';
        }

        # 前端路由
        location / {
            try_files $uri $uri/ /index.html;
        }
    }
}

Docker Compose 配置

开发环境

bash
帮我创建一个开发环境的 docker-compose.yml,包含:
- Node.js 应用(支持热重载)
- PostgreSQL 数据库
- Redis 缓存
- 统一的网络配置
yaml
# docker-compose.yml
version: "3.9"

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
      - DATABASE_URL=postgresql://postgres:postgres@db:5432/myapp_dev
      - REDIS_URL=redis://redis:6379
    volumes:
      - .:/app
      - /app/node_modules
    depends_on:
      - db
      - redis
    command: npm run dev

  db:
    image: postgres:16-alpine
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: myapp_dev
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    command: redis-server --appendonly yes
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 5

volumes:
  postgres_data:
  redis_data:

networks:
  default:
    name: myapp_network

生产环境

yaml
# docker-compose.prod.yml
version: "3.9"

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        - NODE_ENV=production
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
      - REDIS_URL=redis://redis:6379
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy

  db:
    image: postgres:16-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./backup:/backup
    environment:
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: ${DB_NAME}
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5

  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./ssl:/etc/nginx/ssl
    depends_on:
      - app
    restart: unless-stopped

volumes:
  postgres_data:
  redis_data:

开发用 Dockerfile

dockerfile
# Dockerfile.dev
FROM node:20-alpine

WORKDIR /app

# 安装依赖
COPY package*.json ./
RUN npm install

# 挂载源码
COPY . .

# 使用 nodemon 支持热重载
CMD ["npm", "run", "dev"]

常见问题处理

数据库初始化

sql
-- init.sql
-- 创建扩展
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- 创建表
CREATE TABLE IF NOT EXISTS users (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    username VARCHAR(20) NOT NULL UNIQUE,
    email VARCHAR(100) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 创建索引
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);

-- 插入测试数据
INSERT INTO users (username, email, password_hash)
VALUES ('admin', 'admin@example.com', '$2a$10$xxx')
ON CONFLICT (email) DO NOTHING;

数据备份脚本

bash
#!/bin/bash
# backup.sh

DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR=/backup

# 备份 PostgreSQL
docker exec myapp_db_1 pg_dump -U postgres myapp_dev > ${BACKUP_DIR}/db_${DATE}.sql

# 备份 Redis
docker exec myapp_redis_1 redis-cli SAVE
docker cp myapp_redis_1:/data/dump.rdb ${BACKUP_DIR}/redis_${DATE}.rdb

# 清理 7 天前的备份
find ${BACKUP_DIR} -name "*.sql" -mtime +7 -delete
find ${BACKUP_DIR} -name "*.rdb" -mtime +7 -delete

echo "Backup completed: ${DATE}"

Docker 优化技巧

减小镜像体积

dockerfile
# 1. 使用 alpine 基础镜像
FROM node:20-alpine

# 2. 多阶段构建分离依赖和产物
# 3. 合并 RUN 指令减少层数
RUN apt-get update && \
    apt-get install -y package1 package2 && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# 4. 使用 .dockerignore
cat .dockerignore

.dockerignore 示例

# 版本控制 .git .gitignore # 依赖 node_modules npm-debug.log # 开发文件 .env.local .env.*.local *.md .vscode .idea # 测试 coverage *.test.js *.spec.js # 构建产物 .next dist build

常用命令

bash
# 构建镜像
docker build -t myapp:latest .

# 构建并标记
docker build -t myapp:1.0.0 .

# 运行容器
docker run -d -p 3000:3000 --name myapp myapp:latest

# 查看日志
docker logs -f myapp

# 进入容器
docker exec -it myapp sh

# 查看资源使用
docker stats

# 清理未使用的资源
docker system prune -af

# 查看镜像层
docker history myapp:latest

Docker 最佳实践

使用多阶段构建、减小镜像体积、合理利用缓存、避免存储敏感信息。

总结

使用 Claude Code 实现 Docker 容器化:

  • 编写优化过的 Dockerfile
  • 使用多阶段构建减小体积
  • 配置 docker-compose 管理多容器
  • 区分开发环境和生产环境
  • 设置健康检查和日志
  • 定期备份数据