Files
aliyun-manager/Git.md
T

21 KiB
Raw Blame History

Git 私有仓库 + 自动部署流水线 (AI可读)

基于阿里云服务器 8.136.137.59,部署 Gitea 私有 Git 仓库 + Webhook 自动部署流水线。 遵循现有架构:beian-nginx → main-nginx → 服务容器。 所有 Git 相关文件统一放在 /home/Git/,能容器化的全部容器化。


一、架构总览

外网 git.dxz99wyr.cn
    │
    ▼
beian-nginx (:80/:443)
    │  新增: git.dxz99wyr.cn → 172.19.0.1:8080
    ▼
main-nginx (:8080)
    │  新增: git.dxz99wyr.cn → gitea:3000
    ▼
┌─────────────────────────────────────────────┐
│  gitea (Docker)                             │
│  镜像: gitea/gitea:latest                   │
│  内部端口: 3000 (Web UI)                     │
│  内部端口: 22 (SSH Git) → 宿主机映射 2222     │
│  数据卷: /home/Git/gitea/data → /data       │
│  网络: aliyun-app-network                   │
└──────────┬──────────────────────────────────┘
           │ Webhook POST (push 事件)
           │ URL: http://webhook:9000/hooks/xxx
           ▼
┌─────────────────────────────────────────────┐
│  webhook (Docker / 自定义镜像)               │
│  内部端口: 9000                              │
│  内置: git + docker CLI + webhook 二进制     │
│  收到 push → 执行对应脚本                     │
│  网络: aliyun-app-network                   │
│  挂载: docker.sock(操控宿主机 Docker       │
│        /home/Git/webhook/ → 配置只读          │
│        /opt/ALiYunManager/ → 更新代码+重载    │
│        /opt/services/ → 更新各服务代码        │
│        /home/Git/logs/ → 部署日志           │
└──────────┬──────────────────────────────────┘
           │ git clone/pullDocker 内网 HTTP
           │ http://${GITEA_TOKEN}@gitea:3000/...
           │ docker-compose up -d(通过 docker.sock
           ▼
    ┌──────┴──────┬──────────┐
    │             │          │
resume-web   resume-api  其他服务...
 (自动拉代码、构建、重启)

端口规划

端口 用途 对外网 说明
2222 Git SSH 克隆/推送(开发者用) 开放 gitea 容器 22 → 宿主机 2222
3000 Gitea Web UI(容器内部) 不开放 仅 Docker 网络内,通过 nginx 代理
9000 Webhook 接收器(容器内部) 不开放 仅 Docker 网络内,gitea 调用

2222 端口需要在阿里云安全组和服务器防火墙中放行。

宿主机文件总览(仅 /home/Git/ 目录)

/home/Git/
├── gitea/
│   ├── docker-compose.yml    # Gitea 容器定义
│   └── data/                 # Gitea 全部数据(SQLite + 仓库 + 配置)
├── webhook/
│   ├── Dockerfile             # 自定义镜像(git + docker CLI + webhook
│   ├── docker-compose.yml     # Webhook 容器定义
│   ├── hooks.json             # Webhook 路由规则
│   ├── .env                   # GITEA_TOKEN 等敏感变量
│   └── scripts/               # 各服务部署脚本
│       ├── deploy-common.sh
│       ├── deploy-resume-web.sh
│       ├── deploy-resume-api.sh
│       ├── deploy-aliyun-manager.sh
│       └── deploy-miniapp-web.sh
└── logs/
    └── deploy.log             # 部署历史日志

除此之外无需在宿主机创建其他文件。SSH 密钥、Git 配置等均在 Docker 容器内部处理。


二、部署步骤

步骤 1:服务器环境准备

ssh -i "D:\003_Project\小程序连接.pem" root@8.136.137.59

# 创建目录结构(一次性)
mkdir -p /home/Git/gitea/data
mkdir -p /home/Git/webhook/scripts
mkdir -p /home/Git/logs

# 放行 Git SSH 端口
ufw allow 2222/tcp
# 阿里云安全组也需要添加 2222 入方向规则

步骤 2:部署 Gitea 容器

创建 /home/Git/gitea/docker-compose.yml

version: "3.8"

services:
  gitea:
    image: gitea/gitea:latest
    container_name: gitea
    restart: always
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__server__DOMAIN=git.dxz99wyr.cn
      - GITEA__server__SSH_DOMAIN=8.136.137.59
      - GITEA__server__SSH_PORT=2222
      - GITEA__server__ROOT_URL=https://git.dxz99wyr.cn
      - GITEA__server__HTTP_PORT=3000
      - GITEA__server__DISABLE_SSH=false
      - GITEA__database__DB_TYPE=sqlite3
      - GITEA__repository__ENABLE_PUSH_CREATE_USER=true
      - GITEA__repository__ENABLE_PUSH_CREATE_ORG=true
      - GITEA__service__DISABLE_REGISTRATION=true
    ports:
      - "2222:22"
    volumes:
      - /home/Git/gitea/data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    networks:
      - gitea-network

networks:
  gitea-network:
    driver: bridge
    name: aliyun-app-network
cd /home/Git/gitea
docker-compose up -d

# 验证
docker-compose ps
docker-compose logs -f

步骤 3:配置 Nginx 反向代理

3a. main-nginx 配置 — 已存在,确认即可

文件 nginx/conf.d/git.conf(已在项目中创建):

server {
    listen 80;
    server_name git.dxz99wyr.cn;

    access_log /var/log/nginx/git.access.log main;
    error_log /var/log/nginx/git.error.log warn;

    location / {
        proxy_pass http://gitea:3000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
        client_max_body_size 512m;
    }
}

3b. 重载 main-nginx

cd /opt/ALiYunManager
docker-compose exec nginx nginx -t && docker-compose exec nginx nginx -s reload

3c. beian-nginx 追加中转

# 备份
cp /opt/beian-docker/nginx.conf /opt/beian-docker/nginx.conf.bak.$(date +%Y%m%d_%H%M)

# 编辑配置,追加以下 server 块
vim /opt/beian-docker/nginx.conf

http {} 内追加:

# Gitea 私有 Git 仓库
server {
    listen 80;
    server_name git.dxz99wyr.cn;

    location / {
        proxy_pass http://172.19.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
        client_max_body_size 512m;
    }
}
docker exec beian-nginx nginx -t && docker exec beian-nginx nginx -s reload

步骤 4DNS 解析

阿里云域名控制台添加:

记录类型 主机记录 记录值
A git 8.136.137.59

步骤 5:初始化 Gitea

  1. 浏览器访问 http://git.dxz99wyr.cn
  2. 首次访问进入安装页(大部分配置已由 docker-compose.yml 环境变量预设)
  3. 设置管理员账号:
    • 用户名:admin
    • 密码:设置强密码并牢记
    • 邮箱:admin@dxz99wyr.cn
  4. 点击「安装 Gitea」

步骤 6:创建 Gitea 访问令牌(供 Webhook 脚本拉取代码用)

  1. Gitea Web UI → 右上角头像 → SettingsApplications
  2. Generate New Token
    • Token Namedeploy-token
    • 权限:勾选 read:repository
  3. 复制生成的 Token(只显示一次),保存备用

步骤 7:创建仓库

在 Gitea Web UI 中创建:

仓库名 用途
aliyun-manager ALiYunManager 部署项目
resume-web 个人简历前端
resume-api 个人简历后台
miniapp-web 小程序前端
miniapp-api 小程序后台

三、Webhook 自动部署流水线

git push → Gitea → Webhook POST → webhook:9000/hooks/xxx → 对应脚本 → clone/pull → docker-compose 重建

步骤 8:构建 Webhook 自定义镜像

创建 /home/Git/webhook/Dockerfile

# ============================================
# Webhook 接收器自定义镜像
# 内置: docker CLI + git + bash + webhook 二进制
# ============================================
FROM docker:cli

RUN apk add --no-cache git bash curl

ARG WEBHOOK_VERSION=2.8.1
ADD https://github.com/adnanh/webhook/releases/download/${WEBHOOK_VERSION}/webhook-linux-amd64.tar.gz /tmp/
RUN tar -xzf /tmp/webhook-linux-amd64.tar.gz -C /usr/local/bin/ webhook && \
    chmod +x /usr/local/bin/webhook && \
    rm /tmp/webhook-linux-amd64.tar.gz

WORKDIR /opt/webhook

ENTRYPOINT ["/usr/local/bin/webhook"]

步骤 9:创建 Webhook 配置文件

9a. 环境变量 /home/Git/webhook/.env

# Gitea 访问令牌(步骤 6 中生成的)
GITEA_TOKEN=粘贴你的token到这里

# 各个 Webhook Secret(随机生成,与 Gitea Webhook 设置保持一致)
SECRET_RESUME_WEB=resume-web-deploy-secret
SECRET_RESUME_API=resume-api-deploy-secret
SECRET_ALIYUN_MANAGER=aliyun-manager-deploy-secret
SECRET_MINIAPP_WEB=miniapp-web-deploy-secret

9b. Webhook 路由 /home/Git/webhook/hooks.json

[
  {
    "id": "resume-web",
    "execute-command": "/opt/webhook/scripts/deploy-resume-web.sh",
    "command-working-directory": "/opt/webhook/scripts",
    "trigger-rule": {
      "match": {
        "type": "value",
        "value": "resume-web-deploy-secret",
        "parameter": {
          "source": "payload",
          "name": "secret"
        }
      }
    }
  },
  {
    "id": "resume-api",
    "execute-command": "/opt/webhook/scripts/deploy-resume-api.sh",
    "command-working-directory": "/opt/webhook/scripts",
    "trigger-rule": {
      "match": {
        "type": "value",
        "value": "resume-api-deploy-secret",
        "parameter": {
          "source": "payload",
          "name": "secret"
        }
      }
    }
  },
  {
    "id": "aliyun-manager",
    "execute-command": "/opt/webhook/scripts/deploy-aliyun-manager.sh",
    "command-working-directory": "/opt/webhook/scripts",
    "trigger-rule": {
      "match": {
        "type": "value",
        "value": "aliyun-manager-deploy-secret",
        "parameter": {
          "source": "payload",
          "name": "secret"
        }
      }
    }
  },
  {
    "id": "miniapp-web",
    "execute-command": "/opt/webhook/scripts/deploy-miniapp-web.sh",
    "command-working-directory": "/opt/webhook/scripts",
    "trigger-rule": {
      "match": {
        "type": "value",
        "value": "miniapp-web-deploy-secret",
        "parameter": {
          "source": "payload",
          "name": "secret"
        }
      }
    }
  }
]

9c. docker-compose /home/Git/webhook/docker-compose.yml

version: "3.8"

services:
  webhook:
    build: .
    image: webhook-receiver:latest
    container_name: webhook
    restart: always
    ports:
      - "9000:9000"
    env_file:
      - .env
    volumes:
      # Webhook 配置(只读)
      - /home/Git/webhook/hooks.json:/opt/webhook/hooks.json:ro
      - /home/Git/webhook/scripts:/opt/webhook/scripts:ro
      # 部署日志(读写)
      - /home/Git/logs:/opt/webhook/logs
      # 宿主机 Docker 控制权
      - /var/run/docker.sock:/var/run/docker.sock
      # 各项目代码目录(用于 git pull 更新)
      - /opt/ALiYunManager:/opt/ALiYunManager
      - /opt/services/resume-web:/opt/services/resume-web
      - /opt/services/resume-api:/opt/services/resume-api
      - /opt/services/miniapp-web:/opt/services/miniapp-web
    networks:
      - webhook-network
    command:
      - "-hooks=/opt/webhook/hooks.json"
      - "-verbose"
      - "-hot-reload"

networks:
  webhook-network:
    driver: bridge
    name: aliyun-app-network

说明

  • -hot-reload:修改 hooks.json 后无需重启容器
  • 代码目录挂载:webhook 容器直接 git pull 到这些目录,然后通过 docker.sock 执行 docker-compose
  • 容器内部通过 HTTP 访问 gitea:http://gitea:3000,无需 SSH

9d. 通用部署函数 /home/Git/webhook/scripts/deploy-common.sh

#!/bin/bash
# ============================================
# 通用部署函数库
# 被各服务脚本 source 引用
# 运行在 webhook 容器内
# ============================================

set -e

LOG_DIR="/opt/webhook/logs"
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")

log() {
    local SERVICE=$1
    local MESSAGE=$2
    echo "[$TIMESTAMP] [$SERVICE] $MESSAGE" | tee -a "$LOG_DIR/deploy.log"
}

# 从 Gitea 拉取最新代码(Docker 内网 HTTP
# 参数: REPO_NAME GIT_DIR BRANCH
# 使用 GITEA_TOKEN 环境变量认证
clone_or_pull() {
    local REPO_NAME=$1
    local GIT_DIR=$2
    local BRANCH=${3:-main}

    local REPO_URL="http://${GITEA_TOKEN}@gitea:3000/admin/${REPO_NAME}.git"

    if [ -d "$GIT_DIR/.git" ]; then
        log "git" "拉取最新代码: ${REPO_NAME}${GIT_DIR} (分支: ${BRANCH})"
        cd "$GIT_DIR"
        git fetch origin
        git reset --hard "origin/${BRANCH}"
    else
        log "git" "克隆仓库: ${REPO_NAME}${GIT_DIR} (分支: ${BRANCH})"
        git clone -b "$BRANCH" "$REPO_URL" "$GIT_DIR"
    fi
}

# 重建并重启 Docker 服务
# 参数: COMPOSE_DIR SERVICE_NAME
docker_rebuild() {
    local COMPOSE_DIR=$1
    local SERVICE_NAME=$2

    cd "$COMPOSE_DIR"

    if [ -f "Dockerfile" ]; then
        log "$SERVICE_NAME" "构建镜像..."
        docker-compose build "$SERVICE_NAME"
    fi

    log "$SERVICE_NAME" "重启容器..."
    docker-compose up -d --no-deps --force-recreate "$SERVICE_NAME"

    log "$SERVICE_NAME" "部署完成"
}

关键点clone_or_pull 使用 http://${GITEA_TOKEN}@gitea:3000/... 格式, Gitea 和 webhook 同属 aliyun-app-network,直接用容器名 gitea:3000 通信, 不经过外网,也不需要 SSH。

9e. 各服务部署脚本

个人简历前端 /home/Git/webhook/scripts/deploy-resume-web.sh

#!/bin/bash
source /opt/webhook/scripts/deploy-common.sh

SERVICE="resume-web"
REPO_NAME="resume-web"
GIT_DIR="/opt/services/resume-web"
BRANCH="main"

log "$SERVICE" "========== 开始部署 =========="
clone_or_pull "$REPO_NAME" "$GIT_DIR" "$BRANCH"
docker_rebuild "$GIT_DIR" "$SERVICE"
log "$SERVICE" "========== 部署完成 =========="

个人简历后台 /home/Git/webhook/scripts/deploy-resume-api.sh

#!/bin/bash
source /opt/webhook/scripts/deploy-common.sh

SERVICE="resume-api"
REPO_NAME="resume-api"
GIT_DIR="/opt/services/resume-api"
BRANCH="main"

log "$SERVICE" "========== 开始部署 =========="
clone_or_pull "$REPO_NAME" "$GIT_DIR" "$BRANCH"
docker_rebuild "$GIT_DIR" "$SERVICE"
log "$SERVICE" "========== 部署完成 =========="

ALiYunManagernginx 配置部署) /home/Git/webhook/scripts/deploy-aliyun-manager.sh

#!/bin/bash
source /opt/webhook/scripts/deploy-common.sh

SERVICE="aliyun-manager"
REPO_NAME="aliyun-manager"
GIT_DIR="/opt/ALiYunManager"
BRANCH="main"

log "$SERVICE" "========== 开始部署 =========="
clone_or_pull "$REPO_NAME" "$GIT_DIR" "$BRANCH"

cd "$GIT_DIR"

# 重载 main-nginx 配置(不重启容器,零停机)
docker-compose exec -T nginx nginx -t && docker-compose exec -T nginx nginx -s reload
log "$SERVICE" "main-nginx 配置已重载"

log "$SERVICE" "========== 部署完成 =========="

小程序前端 /home/Git/webhook/scripts/deploy-miniapp-web.sh

#!/bin/bash
source /opt/webhook/scripts/deploy-common.sh

SERVICE="miniapp-web"
REPO_NAME="miniapp-web"
GIT_DIR="/opt/services/miniapp-web"
BRANCH="main"

log "$SERVICE" "========== 开始部署 =========="
clone_or_pull "$REPO_NAME" "$GIT_DIR" "$BRANCH"
docker_rebuild "$GIT_DIR" "$SERVICE"
log "$SERVICE" "========== 部署完成 =========="

步骤 10:构建并启动 Webhook 容器

# 赋予脚本执行权限
chmod +x /home/Git/webhook/scripts/*.sh

# 构建自定义镜像并启动
cd /home/Git/webhook
docker-compose build
docker-compose up -d

# 验证
docker-compose ps
docker-compose logs -f

四、Gitea Webhook 配置

对每个仓库,在 Gitea Web UI 中操作:

配置步骤

  1. 进入仓库 → SettingsWebhooks
  2. 点击 Add Webhook → 选择 Gitea
  3. 填写:
字段
Target URL http://webhook:9000/hooks/resume-web(对应 hooks.json 中的 id
HTTP Method POST
POST Content Type application/json
Secret resume-web-deploy-secret(与 hooks.json 和 .env 一致)
Trigger On 勾选 Push
  1. 点击 Add Webhook
  2. 点击 Test Delivery 验证

各仓库 Webhook 配置汇总

仓库 Target URL Secret
resume-web http://webhook:9000/hooks/resume-web resume-web-deploy-secret
resume-api http://webhook:9000/hooks/resume-api resume-api-deploy-secret
aliyun-manager http://webhook:9000/hooks/aliyun-manager aliyun-manager-deploy-secret
miniapp-web http://webhook:9000/hooks/miniapp-web miniapp-web-deploy-secret

Gitea 和 webhook 同属 aliyun-app-network,用容器名 webhook 直接通信。


五、本地开发环境配置

个人 Git 配置

git config --global user.name "Your Name"
git config --global user.email "your-email@example.com"

SSH 密钥(用于 git push

# 生成密钥(如果还没有)
ssh-keygen -t ed25519 -C "your-email@example.com"

# 将公钥添加到 Gitea
cat ~/.ssh/id_ed25519.pub
# Gitea Web UI → Settings → SSH/GPG Keys → Add Key 粘贴

关联远程仓库并推送

# 以 resume-web 为例
cd D:\003_Project\ALiYunManager\services\resume-web

git init
git add .
git commit -m "init"

# 添加远程仓库(走 SSH,端口 2222)
git remote add origin ssh://git@8.136.137.59:2222/admin/resume-web.git

# 推送(此后每次推送自动触发服务器部署)
git push -u origin main

SSH 别名(可选,简化地址)

编辑 ~/.ssh/config

Host gitea
    HostName 8.136.137.59
    Port 2222
    User git
    IdentityFile ~/.ssh/id_ed25519

之后:

git clone gitea:admin/resume-web.git

日常开发流程

git add .
git commit -m "feat: 更新xxx"
git push
# ↑ 推送后自动触发 Webhook → 服务器自动拉代码并部署,无需手动 ssh

六、安全设计

措施 说明
禁用公开注册 DISABLE_REGISTRATION=true
Webhook 仅内网可达 9000 端口无宿主机映射,仅 Docker 网络内 gitea 可调用
独立 Secret 每个仓库使用不同的 Webhook Secret
令牌最小权限 Gitea Token 仅勾选 read:repository,只能拉代码
Token 存于 .env 不硬编码在脚本中,.env 文件权限 600
docker.sock 隔离 webhook 是唯一挂载 docker.sock 的辅助容器,不对外暴露端口

七、完整部署清单(执行顺序)

# 操作 位置
1 mkdir -p /home/Git/{gitea/data,webhook/scripts,logs} 服务器
2 部署 Gitea 容器 /home/Git/gitea/docker-compose.yml
3 重载 main-nginxgit.conf 已就绪) /opt/ALiYunManager/
4 beian-nginx 追加 git 中转 + 重载 /opt/beian-docker/nginx.conf
5 DNS 添加 git A 记录 → 8.136.137.59 阿里云控制台
6 Gitea Web 安装 + 管理员注册 http://git.dxz99wyr.cn
7 生成 Gitea Access Token (read:repository) Gitea Settings → Applications
8 创建各项目仓库 Gitea Web UI
9 填写 /home/Git/webhook/.envGITEA_TOKEN + Secrets 服务器
10 写入 hooks.json + 各部署脚本 /home/Git/webhook/
11 构建自定义镜像 + 启动 webhook 容器 /home/Git/webhook/
12 每个仓库配置 Webhook Gitea Web UI
13 本地推送测试自动部署 开发机

八、故障排查

Webhook 不触发

docker logs webhook -f
# Gitea Web UI → Settings → Webhooks → Recent Deliveries 查看投递状态

部署脚本报错

# 查看部署日志
tail -f /home/Git/logs/deploy.log

# 进入容器手动测试
docker exec -it webhook sh
cd /opt/webhook/scripts
bash deploy-resume-web.sh

Git clone 认证失败

# 检查 Token 是否正确
docker exec webhook env | grep GITEA_TOKEN

# 测试容器内能否访问 Gitea
docker exec webhook curl -s http://gitea:3000/api/v1/version

Gitea 无法访问

docker ps | grep gitea
docker network inspect aliyun-app-network | grep gitea
docker logs gitea -f

九、ICP 备案提醒

git.dxz99wyr.cn 页面底部中间必须显示: 浙ICP备2026030774号-1 并链接到 https://beian.miit.gov.cn

配置方式:Gitea 管理后台 → 自定义 → Footer HTML。