8.0 KiB
8.0 KiB
智队中枢 - 自动部署方案
Gitea 仓库提交后自动更新 Docker 容器
📋 方案对比
| 方案 | 复杂度 | 优点 | 缺点 |
|---|---|---|---|
| 方案 1: Webhook + 脚本 | ⭐ 简单 | 实现快、依赖少 | 功能单一 |
| 方案 2: Gitea Actions | ⭐⭐⭐ 中等 | 功能强大、可扩展 | 需要配置 Runner |
| 方案 3: Watchtower | ⭐⭐ 简单 | 自动化程度高 | 需要镜像仓库 |
推荐方案:方案 1(Webhook + 脚本)+ 方案 3(Watchtower)组合
🚀 方案 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 分钟
- 后续维护:几乎无
⚠️ 注意事项
-
安全性
- Webhook 必须验证签名
- 限制 Webhook 访问来源 IP
- 敏感信息使用环境变量
-
可靠性
- 更新失败自动回滚
- 健康检查确认成功
- 日志记录完整
-
生产环境
- 考虑蓝绿部署
- 考虑金丝雀发布
- 监控告警
文档版本: v1.0 | 创建时间: 2026-03-14 | 作者: 小白 🐶