名称:docker-helper 描述:Docker Compose 生成、优化和故障排除辅助。
Docker 助手技能
Docker Compose 生成、优化和故障排除辅助。
指令
您是 Docker 和容器化专家。当调用时:
-
生成 Docker 文件:
- 根据项目类型创建 Dockerfile
- 为多服务应用生成 docker-compose.yml
- 优化构建时间和镜像大小
- 遵循安全和性能的最佳实践
-
优化现有配置:
- 减少镜像大小(多阶段构建)
- 改进层缓存
- 安全加固
- 资源限制和健康检查
-
故障排除问题:
- 容器启动失败
- 网络连接问题
- 卷挂载问题
- 性能问题
-
提供最佳实践:
- 镜像命名和标签
- 秘密管理
- 日志配置
- 开发与生产配置
Dockerfile 最佳实践
Node.js 应用
# 多阶段构建以减小镜像
FROM node:18-alpine AS builder
WORKDIR /app
# 先复制包文件(更好的层缓存)
COPY package*.json ./
RUN npm ci --only=production
# 复制应用代码
COPY . .
RUN npm run build
# 生产阶段
FROM node:18-alpine
WORKDIR /app
# 以非 root 用户运行
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
# 仅从构建器复制必要文件
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
COPY --chown=nodejs:nodejs package*.json ./
USER nodejs
EXPOSE 3000
# 使用 exec 形式进行正确的信号处理
CMD ["node", "dist/index.js"]
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node healthcheck.js
Python 应用
FROM python:3.11-slim
WORKDIR /app
# 在单独层中安装依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用
COPY . .
# 创建非 root 用户
RUN useradd -m -u 1001 appuser && \
chown -R appuser:appuser /app
USER appuser
EXPOSE 8000
CMD ["python", "app.py"]
Go 应用
# 构建阶段
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
# 最终阶段 - 最小镜像
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]
Docker Compose 示例
全栈应用
version: '3.8'
services:
# 前端
web:
build:
context: ./web
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- API_URL=http://api:8000
depends_on:
api:
condition: service_healthy
networks:
- frontend
restart: unless-stopped
# 后端 API
api:
build:
context: ./api
dockerfile: Dockerfile
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:password@db:5432/myapp
- REDIS_URL=redis://cache:6379
env_file:
- .env
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
networks:
- frontend
- backend
volumes:
- ./logs:/app/logs
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# 数据库
db:
image: postgres:15-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:ro
networks:
- backend
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d myapp"]
interval: 10s
timeout: 5s
retries: 5
# Redis 缓存
cache:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
networks:
- backend
restart: unless-stopped
# Nginx 反向代理
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- web
- api
networks:
- frontend
restart: unless-stopped
networks:
frontend:
driver: bridge
backend:
driver: bridge
volumes:
postgres_data:
redis_data:
开发环境
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
environment:
- NODE_ENV=development
volumes:
- .:/app
- /app/node_modules # 匿名卷用于 node_modules
command: npm run dev
networks:
- dev_network
db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=dev_db
- POSTGRES_USER=dev
- POSTGRES_PASSWORD=dev_password
ports:
- "5432:5432"
volumes:
- dev_db_data:/var/lib/postgresql/data
networks:
- dev_network
volumes:
dev_db_data:
networks:
dev_network:
使用示例
@docker-helper
@docker-helper --generate-dockerfile
@docker-helper --optimize
@docker-helper --compose
@docker-helper --troubleshoot
优化技术
多阶段构建
# 通过 70-90% 减少最终镜像大小
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]
层缓存
# ❌ 坏 - 任何文件更改都会使缓存失效
COPY . .
RUN npm install
# ✓ 好 - 单独缓存依赖
COPY package*.json ./
RUN npm install
COPY . .
减少镜像大小
# 使用 alpine 变体(小得多)
FROM node:18-alpine # ~170MB 对比 node:18 的 ~900MB
# 在同一层中清理
RUN apt-get update && \
apt-get install -y package && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# 使用 .dockerignore
# 创建 .dockerignore 文件:
# node_modules
# .git
# *.md
# .env*
安全最佳实践
# 不要以 root 运行
RUN adduser -D -u 1001 appuser
USER appuser
# 扫描漏洞
# 使用:docker scan myimage:tag
# 使用特定标签,不是 'latest'
FROM node:18.16.0-alpine # 不是:FROM node:latest
# 不要在镜像中存储秘密
# 使用环境变量或秘密管理
# 最小化攻击面
# 使用最小基础镜像(alpine, distroless)
# 保持基础镜像更新
# 定期重建和更新
常见问题与解决方案
问题:容器立即退出
# 检查日志
docker logs <container_id>
# 交互式运行以调试
docker run -it <image> /bin/sh
# 检查入口点/命令
docker inspect <container_id> | grep -A5 Cmd
问题:无法连接到服务
# 确保服务在同一网络
networks:
- mynetwork
# 使用服务名称作为主机名
DATABASE_URL=postgresql://db:5432/myapp # 'db' 是服务名称
# 检查服务是否就绪
depends_on:
db:
condition: service_healthy
问题:卷权限问题
# 匹配主机用户 ID
RUN adduser -u 1001 appuser
USER appuser
# 或在入口点更改所有权
ENTRYPOINT ["sh", "-c", "chown -R appuser:appuser /data && exec \"$@\""]
问题:构建缓慢
# 有效使用构建缓存
COPY package*.json ./
RUN npm ci
COPY . .
# 使用 BuildKit
# 设置:DOCKER_BUILDKIT=1
# 使用 .dockerignore
# 排除:node_modules, .git, 构建产物
Docker 命令参考
# 构建镜像
docker build -t myapp:latest .
# 运行容器
docker run -d -p 3000:3000 --name myapp myapp:latest
# 查看日志
docker logs -f myapp
# 在容器中执行命令
docker exec -it myapp /bin/sh
# 停止并删除
docker stop myapp && docker rm myapp
# Compose 命令
docker-compose up -d
docker-compose down
docker-compose logs -f
docker-compose ps
# 清理
docker system prune -a
docker volume prune
健康检查
# Node.js
HEALTHCHECK --interval=30s --timeout=3s \
CMD node healthcheck.js || exit 1
# Python
HEALTHCHECK --interval=30s --timeout=3s \
CMD python -c "import requests; requests.get('http://localhost:8000/health')" || exit 1
# 简单 HTTP 检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://localhost:8000/health || exit 1
注意事项
- 始终使用特定版本标签,不是
latest - 为关键服务实施健康检查
- 使用多阶段构建以减少镜像大小
- 永远不要在 Dockerfile 或镜像中存储秘密
- 使用
.dockerignore排除不必要文件 - 以非 root 用户运行容器
- 实施适当的日志记录(stdout/stderr)
- 使用卷进行持久数据
- 在生产中配置资源限制
- 定期更新基础镜像以获取安全补丁