用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/huanglei288766/claude-code-zh --skill docker-cicd命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| name | docker-cicd |
| description | Docker 容器化与 CI/CD 流水线最佳实践,涵盖 Dockerfile 优化、docker-compose 编排、GitHub Actions 部署、镜像管理 |
| version | 1.0 |
本 Skill 提供 Docker 容器化和 CI/CD 流水线的完整实践指南,包含 Dockerfile 最佳实践、开发环境编排、GitHub Actions 自动化部署等。
适用场景:
# ===== 第一阶段:构建 =====
FROM maven:3.9-eclipse-temurin-21-alpine AS builder
WORKDIR /build
# 先拷贝 pom.xml,利用 Docker 缓存层加速依赖下载
COPY pom.xml .
RUN mvn dependency:go-offline -B
# 拷贝源码并构建
COPY src ./src
RUN mvn package -DskipTests -B \
&& java -Djarmode=layertools -jar target/*.jar extract --destination extracted
# ===== 第二阶段:运行 =====
FROM eclipse-temurin:21-jre-alpine AS runtime
# 安全:创建非 root 用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
# 按变化频率从低到高拷贝分层(充分利用缓存)
COPY --from=builder /build/extracted/dependencies/ ./
COPY --from=builder /build/extracted/spring-boot-loader/ ./
COPY --from=builder /build/extracted/snapshot-dependencies/ ./
COPY --from=builder /build/extracted/application/ ./
# 使用非 root 用户运行
USER appuser
# 暴露端口
EXPOSE 8080
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
CMD wget -qO- http://localhost:8080/actuator/health || exit 1
# JVM 参数优化:容器感知内存限制
ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -XX:InitialRAMPercentage=50.0"
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS org.springframework.boot.loader.launch.JarLauncher"]
# ===== 第一阶段:安装依赖 =====
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile
# ===== 第二阶段:构建 =====
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN corepack enable && pnpm build
# ===== 第三阶段:运行 =====
FROM node:20-alpine AS runtime
# 安全:非 root 用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
# 只拷贝生产依赖和构建产物
COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package.json ./
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "dist/main.js"]
# 1. 使用 alpine 基础镜像(体积最小)
FROM eclipse-temurin:21-jre-alpine # 约 100MB vs 标准版 300MB+
# 2. 合并 RUN 指令,减少层数
RUN apk add --no-cache curl tzdata \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone \
&& apk del tzdata
# 3. 使用 .dockerignore 排除无关文件
# .dockerignore 内容:
# .git
# .idea
# target/
# node_modules/
# *.md
# docker-compose*.yml
# .env*
# 4. 清理构建缓存
RUN mvn package -DskipTests \
&& rm -rf ~/.m2/repository # 多阶段构建时非最终阶段可清理
# 5. 不安装不必要的包
RUN apk add --no-cache --virtual .build-deps gcc musl-dev \
&& pip install --no-cache-dir -r requirements.txt \
&& apk del .build-deps
# 使用 Trivy 扫描镜像漏洞
trivy image --severity HIGH,CRITICAL myapp:latest
# 使用 Hadolint 检查 Dockerfile 规范
hadolint Dockerfile
# 使用 Dockle 检查容器最佳实践
dockle myapp:latest
# 在 CI 中集成扫描(见 GitHub Actions 章节)
# docker-compose.yml — 本地开发环境
version: "3.8"
services:
# ===== 应用服务 =====
app:
build:
context: .
dockerfile: Dockerfile
target: builder # 开发时使用构建阶段,方便调试
ports:
- "8080:8080"
- "5005:5005" # 远程调试端口
environment:
- SPRING_PROFILES_ACTIVE=dev
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/mydb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=dev123456
- SPRING_DATA_REDIS_HOST=redis
- SPRING_DATA_REDIS_PORT=6379
- SPRING_ELASTICSEARCH_URIS=http://elasticsearch:9200
- JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
volumes:
- ./src:/build/src # 挂载源码,支持热重载
- maven-cache:/root/.m2 # 缓存 Maven 依赖
depends_on:
mysql:
condition: service_healthy
redis:
[, , , , , , , ]
[, , , , ]
[, ]
# 启动所有服务
docker compose up -d
# 启动含可选服务(如 Kibana)
docker compose --profile debug up -d
# 查看日志
docker compose logs -f app
# 仅重建应用服务
docker compose up -d --build app
# 清理所有数据卷(慎用)
docker compose down -v
# 进入容器调试
docker compose exec mysql mysql -u root -pdev123456 mydb
docker compose exec redis redis-cli -a dev123456
# .github/workflows/ci-cd.yml
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
# 支持手动触发
workflow_dispatch:
# 同一分支只保留最新的一次运行
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
JAVA_VERSION: "21"
jobs:
# ===== 阶段一:代码检查 =====
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 设置 Java 环境
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: ${{ env.JAVA_VERSION
# 格式:{仓库}/{项目}:{标签}
ghcr.io/myorg/myapp:latest # 最新稳定版(仅 main 分支)
ghcr.io/myorg/myapp:1.2.3 # 语义化版本(推荐生产使用)
ghcr.io/myorg/myapp:1.2 # 主次版本(自动获取最新 patch)
ghcr.io/myorg/myapp:main-a1b2c3d # 分支 + commit SHA
ghcr.io/myorg/myapp:develop-a1b2c3d # 开发分支 + commit SHA
规则 说明
─────────────────────────────────────────────────────────────
生产环境必须用具体版本号 禁止使用 latest
测试环境使用 branch-sha 格式 便于追溯
基础镜像锁定版本 FROM node:20.11.1-alpine(非 latest)
定期更新基础镜像 修复已知漏洞
镜像保留策略 保留最近 30 个版本,定期清理旧镜像
# .github/workflows/release.yml — 基于 tag 自动发布
name: Release
on:
push:
tags:
- "v*.*.*" # 匹配 v1.0.0 格式
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 提取版本号
id: version
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
- name: 构建并推送正式版镜像
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository }}:${{ steps.version.outputs.VERSION }}
ghcr.io/${{ github.repository }}:latest
- name: 创建 GitHub Release
uses: softprops/action-gh-release@v1
with:
generate_release_notes: true
// 自定义健康检查指标
@Component
public class DatabaseHealthIndicator implements HealthIndicator {
private final DataSource dataSource;
public DatabaseHealthIndicator(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public Health health() {
try (Connection conn = dataSource.getConnection()) {
// 执行简单查询验证连接可用
conn.createStatement().execute("SELECT 1");
return Health.up()
.withDetail("database", "MySQL")
.withDetail("status", "连接正常")
.build();
} catch (Exception e) {
return Health.down()
.withDetail("database", "MySQL")
.withDetail("error", e.getMessage())
.build();
}
}
}
# application.yml — 健康检查配置
management:
endpoints:
web:
exposure:
include: health,info,metrics
endpoint:
health:
show-details: when-authorized # 仅授权用户可见详情
probes:
enabled: true # 启用 K8s 探针
health:
# 各组件健康检查开关
db:
enabled: true
redis:
enabled: true
elasticsearch:
enabled: true
diskspace:
enabled: true
threshold: 100MB # 磁盘空间阈值
# 健康检查最佳实践
services:
app:
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/actuator/health/liveness || exit 1"]
interval: 30s # 检查间隔
timeout: 3s # 超时时间
retries: 3 # 连续失败几次标记为不健康
start_period: 60s # 启动宽限期(JVM 启动较慢)
# 依赖健康检查实现启动顺序控制
worker:
depends_on:
app:
condition: service_healthy
mysql:
condition: service_healthy
# 版本控制
.git
.gitignore
# IDE
.idea
.vscode
*.iml
# 构建产物
target/
dist/
build/
node_modules/
# 文档
*.md
LICENSE
docs/
# Docker 自身配置
Dockerfile*
docker-compose*
.dockerignore
# 环境变量(敏感信息)
.env
.env.*
# 测试
test/
tests/
__tests__/
coverage/
.nyc_output/
# CI/CD
.github/
.gitlab-ci.yml
Jenkinsfile
# OS 文件
.DS_Store
Thumbs.db
| 问题 | 解决方案 |
|---|---|
| 镜像体积过大 | 使用多阶段构建 + alpine 基础镜像 |
| 构建缓慢 | 合理利用缓存层,先 COPY 依赖文件再 COPY 源码 |
| 容器时区不对 | 设置 TZ=Asia/Shanghai 环境变量 |
| 容器内无法连接宿主机服务 | 使用 host.docker.internal(macOS/Windows) |
| compose 服务启动顺序 | 使用 depends_on + condition: service_healthy |
| 生产环境用了 latest 标签 | 改为具体版本号,CI 中自动生成 tag |
| 镜像有安全漏洞 | 集成 Trivy 扫描,更新基础镜像 |
| 日志未持久化 | 使用日志驱动或挂载卷 |