# 智队中枢 - 自动部署方案 > Gitea 仓库提交后自动更新 Docker 容器 ## 📋 方案对比 | 方案 | 复杂度 | 优点 | 缺点 | |------|--------|------|------| | **方案 1: Webhook + 脚本** | ⭐ 简单 | 实现快、依赖少 | 功能单一 | | **方案 2: Gitea Actions** | ⭐⭐⭐ 中等 | 功能强大、可扩展 | 需要配置 Runner | | **方案 3: Watchtower** | ⭐⭐ 简单 | 自动化程度高 | 需要镜像仓库 | **推荐方案**:方案 1(Webhook + 脚本)+ 方案 3(Watchtower)组合 --- ## 🚀 方案 1: Gitea Webhook + 更新脚本 ### 架构流程 ``` 开发者推送代码 ↓ Gitea 仓库接收推送 ↓ 触发 Webhook (push 事件) ↓ Webhook 服务接收请求 ↓ 验证签名 + 执行更新脚本 ↓ 拉取最新代码 → 构建镜像 → 重启容器 ↓ 发送通知(可选) ``` ### 实现步骤 #### 1. 创建更新脚本 ```bash #!/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 服务 ```python # /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 服务 ```ini # /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 ```bash 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 执行工作流 ↓ 构建 → 测试 → 推送镜像 → 部署 ↓ 通知结果 ``` ### 工作流配置 ```yaml # .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 ```bash # 创建 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= \ gitea/act_runner:latest ``` --- ## 📦 方案 3: Watchtower(自动监控镜像更新) ### 适用场景 适用于已经推送到镜像仓库的场景。 ### 配置 ```yaml # 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 | 作者: 小白 🐶*