香港服务器Gitea + Harbor + Woodpecker完整DevOps流水线:代码到镜像到部署全自动化

香港服务器Gitea + Harbor + Woodpecker完整DevOps流水线:代码到镜像到部署全自动化

前面章节分别部署了 Gitea(代码仓库)、Harbor(镜像仓库)、Woodpecker CI(流水线)。本文将三者完整打通,实现:git push → Woodpecker 自动触发 → 构建 Docker 镜像 → Trivy 安全扫描 → 推送 Harbor → SSH 部署到生产服务器 → 发送飞书通知,每次代码推送10分钟内完成全自动部署。


一、完整流水线架构

<code">
开发者 git push → Gitea
    │  Webhook 触发
    ▼
Woodpecker CI(流水线调度)
    │
    ├── Step 1: 单元测试
    │
    ├── Step 2: 构建 Docker 镜像
    │           docker build -t myapp:${CI_COMMIT_SHA}
    │
    ├── Step 3: Trivy 安全扫描
    │           发现 HIGH/CRITICAL → 流水线失败,阻止部署
    │
    ├── Step 4: 推送到 Harbor
    │           docker push registry.yourdomain.com/myapp:${SHA}
    │
    ├── Step 5: 部署到生产服务器
    │           SSH → docker pull → docker restart
    │
    └── Step 6: 健康检查 + 飞书通知

二、完整 Woodpecker 流水线配置

<code"># .woodpecker.yml(放在 Gitea 仓库根目录)
---
when:
  event: push
  branch: main

# 全局变量
variables:
  - &registry "registry.yourdomain.com"
  - &image "registry.yourdomain.com/myapp/backend"

steps:
  # ── 步骤1:运行测试 ──
  test:
    image: python:3.12-slim
    commands:
      - pip install -r requirements.txt --quiet
      - pytest tests/ -v --tb=short --junitxml=test-results.xml
    when:
      event: [push, pull_request]

  # ── 步骤2:构建 Docker 镜像 ──
  build:
    image: docker:24-dind
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      REGISTRY: *registry
    commands:
      - docker login $REGISTRY
          -u ${HARBOR_USER}
          -p ${HARBOR_PASSWORD}
      - docker build
          --build-arg BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
          --build-arg VCS_REF=${CI_COMMIT_SHA:0:8}
          -t *image:${CI_COMMIT_SHA:0:8}
          -t *image:latest
          .
    secrets: [harbor_user, harbor_password]
    when:
      event: push
      branch: main

  # ── 步骤3:Trivy 安全扫描 ──
  security-scan:
    image: aquasec/trivy:latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /tmp/trivy-cache:/root/.cache/trivy
    commands:
      - trivy image
          --severity HIGH,CRITICAL
          --exit-code 1
          --no-progress
          --format table
          *image:${CI_COMMIT_SHA:0:8}
    when:
      event: push
      branch: main

  # ── 步骤4:推送到 Harbor ──
  push:
    image: docker:24-dind
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    commands:
      - docker push *image:${CI_COMMIT_SHA:0:8}
      - docker push *image:latest
    secrets: [harbor_user, harbor_password]
    depends_on: [security-scan]   # 扫描通过后才推送
    when:
      event: push
      branch: main

  # ── 步骤5:部署到生产服务器 ──
  deploy:
    image: appleboy/drone-ssh:latest
    settings:
      host:
        from_secret: prod_server_host
      username: deploy
      key:
        from_secret: deploy_ssh_key
      port: 2222
      script:
        - |
          echo "开始部署 *image:${CI_COMMIT_SHA:0:8}..."
          docker login registry.yourdomain.com
            -u ${HARBOR_USER} -p ${HARBOR_PASSWORD}
          docker pull *image:${CI_COMMIT_SHA:0:8}
          docker stop myapp-backend || true
          docker rm myapp-backend || true
          docker run -d \
            --name myapp-backend \
            --restart unless-stopped \
            -p 127.0.0.1:8000:8000 \
            --env-file /opt/myapp/.env \
            --label "deploy.sha=${CI_COMMIT_SHA:0:8}" \
            --label "deploy.time=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
            *image:${CI_COMMIT_SHA:0:8}
          sleep 5
          curl -sf http://localhost:8000/health || exit 1
          echo "✅ 部署成功!版本:${CI_COMMIT_SHA:0:8}"
    depends_on: [push]
    when:
      event: push
      branch: main

  # ── 步骤6:飞书通知 ──
  notify:
    image: curlimages/curl:latest
    environment:
      FEISHU_WEBHOOK:
        from_secret: feishu_webhook
    commands:
      - |
        STATUS="✅ 部署成功"
        COLOR="green"
        if [ "${CI_PIPELINE_STATUS}" != "success" ]; then
          STATUS="❌ 部署失败"
          COLOR="red"
        fi
        curl -s -X POST "$FEISHU_WEBHOOK" \
          -H "Content-Type: application/json" \
          -d "{
            \"msg_type\": \"interactive\",
            \"card\": {
              \"header\": {\"title\": {\"content\": \"$STATUS\", \"tag\": \"plain_text\"}, \"template\": \"$COLOR\"},
              \"elements\": [{\"tag\": \"div\", \"text\": {\"tag\": \"lark_md\",
                \"content\": \"**仓库:** ${CI_REPO_NAME}\\n**分支:** ${CI_COMMIT_BRANCH}\\n**提交:** ${CI_COMMIT_SHA:0:8}\\n**提交者:** ${CI_COMMIT_AUTHOR}\\n**消息:** ${CI_COMMIT_MESSAGE}\"
              }}]
            }
          }"
    when:
      status: [success, failure]   # 无论成功失败都通知

三、在 Woodpecker 中配置 Secrets

<code">
在 Woodpecker Web UI → 仓库 → Settings → Secrets:

harbor_user     → Harbor 用户名
harbor_password → Harbor 密码
prod_server_host → 生产服务器 IP
deploy_ssh_key  → SSH 私钥(PEM 格式,完整内容)
feishu_webhook  → 飞书 Webhook URL

或通过 Woodpecker CLI:
woodpecker-cli secret add -repo myorg/myapp -name harbor_user -value "deploy"
woodpecker-cli secret add -repo myorg/myapp -name harbor_password -value "xxxxx"

四、Harbor 推送策略(扫描通过才允许拉取)

<code">
在 Harbor Web UI 配置:

1. 仓库 → myapp → 配置
   - 自动扫描:推送时自动扫描 ✅
   - 阻止漏洞镜像:严重性 >= HIGH → 阻止拉取 ✅

2. 效果:
   - Woodpecker 推送镜像到 Harbor
   - Harbor 自动扫描
   - 如果发现高危漏洞,Harbor 阻止该镜像被拉取
   - 生产服务器尝试 docker pull 时失败,保护生产环境

五、总结

Gitea + Harbor + Woodpecker 的自托管 DevOps 三件套,在香港服务器上实现了与 GitHub + GHCR + GitHub Actions 等价的功能,且完全自主可控、无额外费用。整套流水线从 git push 到生产部署完成约 8~12 分钟,安全扫描阻断了已知漏洞上线,飞书通知让团队实时感知部署状态,是中小团队 DevOps 工程化的完整起点。

Telegram