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:latestDocker 最佳实践
使用多阶段构建、减小镜像体积、合理利用缓存、避免存储敏感信息。
总结
使用 Claude Code 实现 Docker 容器化:
- 编写优化过的 Dockerfile
- 使用多阶段构建减小体积
- 配置 docker-compose 管理多容器
- 区分开发环境和生产环境
- 设置健康检查和日志
- 定期备份数据