Files
pit-router/docs/AUTO_DEPLOY.md
yunxiafei 1b41e28499 docs: 添加自动部署方案到 README
功能:
- Gitea Webhook + 更新脚本方案
- 自动拉取代码、构建镜像、重启容器
- 健康检查确认更新成功

作者: 小白 🐶
2026-03-14 22:27:37 +08:00

8.0 KiB
Raw Permalink Blame History

智队中枢 - 自动部署方案

Gitea 仓库提交后自动更新 Docker 容器

📋 方案对比

方案 复杂度 优点 缺点
方案 1: Webhook + 脚本 简单 实现快、依赖少 功能单一
方案 2: Gitea Actions 中等 功能强大、可扩展 需要配置 Runner
方案 3: Watchtower 简单 自动化程度高 需要镜像仓库

推荐方案:方案 1Webhook + 脚本)+ 方案 3Watchtower组合


🚀 方案 1: Gitea Webhook + 更新脚本

架构流程

开发者推送代码
       ↓
Gitea 仓库接收推送
       ↓
触发 Webhook (push 事件)
       ↓
Webhook 服务接收请求
       ↓
验证签名 + 执行更新脚本
       ↓
拉取最新代码 → 构建镜像 → 重启容器
       ↓
发送通知(可选)

实现步骤

1. 创建更新脚本

#!/bin/bash
# /www/wwwroot/pit-router/auto-update.sh

set -e

LOG_FILE="/var/log/pit-router-update.log"
REPO_DIR="/www/wwwroot/pit-router"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

log "========== 开始自动更新 =========="

cd "$REPO_DIR"

# 1. 拉取最新代码
log "拉取最新代码..."
git fetch origin
git reset --hard origin/main

# 2. 停止旧容器
log "停止旧容器..."
docker-compose down

# 3. 构建新镜像
log "构建新镜像..."
docker-compose build --no-cache

# 4. 启动新容器
log "启动新容器..."
docker-compose up -d

# 5. 等待健康检查
log "等待服务启动..."
sleep 10

# 6. 健康检查
if curl -sf http://localhost:1999/health > /dev/null; then
    log "✅ 更新成功!服务运行正常"
else
    log "❌ 更新失败!服务未正常启动"
    exit 1
fi

log "========== 更新完成 =========="

2. 创建 Webhook 服务

# /www/wwwroot/pit-router/webhook-server.py

from flask import Flask, request, jsonify
import hmac
import hashlib
import subprocess
import os

app = Flask(__name__)

# 配置
WEBHOOK_SECRET = os.environ.get('WEBHOOK_SECRET', 'your-webhook-secret')
UPDATE_SCRIPT = '/www/wwwroot/pit-router/auto-update.sh'

def verify_signature(payload, signature):
    """验证 Webhook 签名"""
    expected = 'sha256=' + hmac.new(
        WEBHOOK_SECRET.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

@app.route('/webhook/pit-router', methods=['POST'])
def handle_webhook():
    """处理 Gitea Webhook"""
    # 验证签名
    signature = request.headers.get('X-Gitea-Signature', '')
    if not verify_signature(request.data, signature):
        return jsonify({'error': 'Invalid signature'}), 401
    
    # 解析事件
    event = request.headers.get('X-Gitea-Event', '')
    if event != 'push':
        return jsonify({'message': 'Event ignored'}), 200
    
    data = request.json
    ref = data.get('ref', '')
    
    # 只处理 main 分支
    if ref != 'refs/heads/main':
        return jsonify({'message': 'Branch ignored'}), 200
    
    # 执行更新脚本
    try:
        result = subprocess.run(
            [UPDATE_SCRIPT],
            capture_output=True,
            text=True,
            timeout=300
        )
        
        if result.returncode == 0:
            return jsonify({
                'status': 'success',
                'message': 'Update completed',
                'output': result.stdout
            })
        else:
            return jsonify({
                'status': 'error',
                'message': result.stderr
            }), 500
            
    except subprocess.TimeoutExpired:
        return jsonify({'error': 'Update timeout'}), 500
    except Exception as e:
        return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5001)

3. 创建 systemd 服务

# /etc/systemd/system/pit-router-webhook.service

[Unit]
Description=PIT Router Webhook Server
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/www/wwwroot/pit-router
Environment=WEBHOOK_SECRET=your-webhook-secret
ExecStart=/usr/bin/python3 /www/wwwroot/pit-router/webhook-server.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

4. 配置 Gitea Webhook

TOKEN="509149b911143135084d20c44fc97a462a16945a"

# 创建 Webhook
curl -X POST "http://localhost:3000/api/v1/repos/yunxiafei/pit-router/hooks" \
  -H "Authorization: token $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "gitea",
    "config": {
      "url": "http://localhost:5001/webhook/pit-router",
      "content_type": "json",
      "secret": "your-webhook-secret"
    },
    "events": ["push"],
    "active": true
  }'

🔄 方案 2: Gitea Actions推荐用于复杂项目

架构流程

开发者推送代码
       ↓
Gitea Actions 触发
       ↓
Runner 执行工作流
       ↓
构建 → 测试 → 推送镜像 → 部署
       ↓
通知结果

工作流配置

# .gitea/workflows/deploy.yml

name: Build and Deploy

on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      
      - name: Set up Docker
        uses: docker/setup-buildx-action@v3
      
      - name: Build Image
        run: |
          docker build -t pit-router:latest .
      
      - name: Run Tests
        run: |
          docker run --rm pit-router:latest python -m pytest tests/
      
      - name: Deploy
        run: |
          docker-compose down
          docker-compose up -d
      
      - name: Health Check
        run: |
          sleep 10
          curl -sf http://localhost:1999/health || exit 1

配置 Gitea Actions Runner

# 创建 Runner Token
TOKEN="509149b911143135084d20c44fc97a462a16945a"

curl -X POST "http://localhost:3000/api/v1/admin/runners/registration-token" \
  -H "Authorization: token $TOKEN"

# 安装 Runner
docker run -d \
  --name gitea-runner \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /www/wwwroot/pit-router:/workspace \
  -e GITEA_INSTANCE_URL=http://localhost:3000 \
  -e GITEA_RUNNER_REGISTRATION_TOKEN=<token> \
  gitea/act_runner:latest

📦 方案 3: Watchtower自动监控镜像更新

适用场景

适用于已经推送到镜像仓库的场景。

配置

# docker-compose.yaml 添加 watchtower

  watchtower:
    image: containrrr/watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WATCHTOWER_CLEANUP=true
      - WATCHTOWER_POLL_INTERVAL=300  # 每 5 分钟检查一次
      - WATCHTOWER_NOTIFICATIONS=email
      - WATCHTOWER_NOTIFICATION_EMAIL_FROM=alert@example.com
      - WATCHTOWER_NOTIFICATION_EMAIL_TO=admin@example.com
      - WATCHTOWER_NOTIFICATION_EMAIL_SERVER=smtp.example.com
    restart: unless-stopped

🎯 推荐方案

简单场景(当前推荐)

方案 1: Webhook + 脚本

项目 说明
复杂度
依赖 Flask + 简单脚本
部署时间 30 分钟
维护成本

复杂场景(未来扩展)

方案 2: Gitea Actions

项目 说明
复杂度
依赖 Gitea Runner
功能 测试、构建、部署一体化
维护成本

📝 实施清单

方案 1 实施步骤

  • 创建更新脚本 auto-update.sh
  • 创建 Webhook 服务 webhook-server.py
  • 创建 systemd 服务
  • 配置 Gitea Webhook
  • 测试自动更新流程

预计时间

  • 首次部署30 分钟
  • 后续维护:几乎无

⚠️ 注意事项

  1. 安全性

    • Webhook 必须验证签名
    • 限制 Webhook 访问来源 IP
    • 敏感信息使用环境变量
  2. 可靠性

    • 更新失败自动回滚
    • 健康检查确认成功
    • 日志记录完整
  3. 生产环境

    • 考虑蓝绿部署
    • 考虑金丝雀发布
    • 监控告警

文档版本: v1.0 | 创建时间: 2026-03-14 | 作者: 小白 🐶