From 393b42f35a09dc9832d994ce830a28c67b7b09db Mon Sep 17 00:00:00 2001 From: shanshanzhong Date: Fri, 10 Oct 2025 07:23:12 -0700 Subject: [PATCH] =?UTF-8?q?ci:=20=E6=B7=BB=E5=8A=A0Docker=E6=9E=84?= =?UTF-8?q?=E5=BB=BA=E5=92=8C=E9=83=A8=E7=BD=B2=E7=9A=84Gitea=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加用于构建Docker镜像并部署到生产环境的Gitea工作流配置 包含构建、推送镜像、服务器部署和Telegram通知功能 支持根据分支自动设置不同环境变量 --- .gitea/workflows/docker.yml | 231 ++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 .gitea/workflows/docker.yml diff --git a/.gitea/workflows/docker.yml b/.gitea/workflows/docker.yml new file mode 100644 index 0000000..9d19a63 --- /dev/null +++ b/.gitea/workflows/docker.yml @@ -0,0 +1,231 @@ +name: Build docker and publish +run-name: 简化的Docker构建和部署流程 + +on: + push: + branches: + - main + - dev + pull_request: + branches: + - main + - dev + +env: + # Docker镜像仓库 + REPO: ${{ vars.REPO || 'registry.kxsw.us/ario-server' }} + # SSH连接信息 + SSH_HOST: ${{ vars.SSH_HOST }} + SSH_PORT: ${{ vars.SSH_PORT }} + SSH_USER: ${{ vars.SSH_USER }} + SSH_PASSWORD: ${{ vars.SSH_PASSWORD }} + # TG通知 + TG_BOT_TOKEN: 8114337882:AAHkEx03HSu7RxN4IHBJJEnsK9aPPzNLIk0 + TG_CHAT_ID: "-4940243803" + # Go构建变量 + SERVICE: ppanel + SERVICE_STYLE: ppanel + VERSION: ${{ github.sha }} + BUILDTIME: ${{ github.event.head_commit.timestamp }} + GOARCH: amd64 + +jobs: + build: + runs-on: ario-server + container: + image: node:20 + strategy: + matrix: + # 只有node支持版本号别名 + node: ['20.15.1'] + steps: + # 步骤1: 下载代码 + - name: 📥 下载代码 + uses: actions/checkout@v4 + + # 步骤2: 设置动态环境变量 + - name: ⚙️ 设置动态环境变量 + run: | + if [ "${{ github.ref_name }}" = "main" ]; then + echo "DOCKER_TAG_SUFFIX=latest" >> $GITHUB_ENV + echo "CONTAINER_NAME=ppanel-server" >> $GITHUB_ENV + echo "DEPLOY_PATH=/root/vpn_server" >> $GITHUB_ENV + echo "为 main 分支设置生产环境变量" + elif [ "${{ github.ref_name }}" = "dev" ]; then + echo "DOCKER_TAG_SUFFIX=dev" >> $GITHUB_ENV + echo "CONTAINER_NAME=ppanel-server-dev" >> $GITHUB_ENV + echo "DEPLOY_PATH=/root/vpn_server_dev" >> $GITHUB_ENV + echo "为 dev 分支设置开发环境变量" + else + echo "DOCKER_TAG_SUFFIX=${{ github.ref_name }}" >> $GITHUB_ENV + echo "CONTAINER_NAME=ppanel-server-${{ github.ref_name }}" >> $GITHUB_ENV + echo "DEPLOY_PATH=/root/vpn_server_other" >> $GITHUB_ENV + echo "为其他分支 (${{ github.ref_name }}) 设置环境变量" + fi + + # 步骤3: 安装系统工具 (Docker, curl, jq) + - name: 🔧 安装系统工具 (Docker, curl, jq) + run: | + set -e + export DEBIAN_FRONTEND=noninteractive + echo "等待 apt/dpkg 锁释放 (unattended-upgrades)..." + # 等待最多 300 秒让 unattended-upgrades/apt/dpkg 锁释放 + end=$((SECONDS+300)) + while true; do + LOCKS_BUSY=0 + # 如果 unattended-upgrades 正在运行,标记为忙碌 + if pgrep -x unattended-upgrades >/dev/null 2>&1; then LOCKS_BUSY=1; fi + # 如果 fuser 存在,检查常见的锁文件 + if command -v fuser >/dev/null 2>&1; then + if fuser /var/lib/dpkg/lock >/dev/null 2>&1 \ + || fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 \ + || fuser /var/lib/apt/lists/lock >/dev/null 2>&1; then + LOCKS_BUSY=1 + fi + fi + # 如果不忙碌则跳出循环 + if [ "$LOCKS_BUSY" -eq 0 ]; then break; fi + # 超时后约 5 分钟 + if [ $SECONDS -ge $end ]; then + echo "等待 apt/dpkg 锁超时,使用 Dpkg::Lock::Timeout 继续..." + break + fi + echo "仍在等待锁释放..."; sleep 5 + done + apt-get update -y -o Dpkg::Lock::Timeout=600 + apt-get install -y -o Dpkg::Lock::Timeout=600 jq curl ca-certificates docker.io + docker --version + jq --version + curl --version + + # 步骤4: 构建并发布到镜像仓库 + - name: 📤 构建并发布到镜像仓库 + run: | + echo "开始构建并推送镜像..." + echo "仓库: ${{ env.REPO }}" + echo "版本标签: ${{ env.VERSION }}" + echo "分支标签: ${{ env.DOCKER_TAG_SUFFIX }}" + + # 构建镜像,同时打上版本和分支两个标签 + docker build -f Dockerfile \ + --platform linux/amd64 \ + --build-arg TARGETARCH=amd64 \ + --build-arg VERSION=${{ env.VERSION }} \ + --build-arg BUILDTIME=${{ env.BUILDTIME }} \ + -t ${{ env.REPO }}:${{ env.VERSION }} \ + -t ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }} \ + . + + echo "推送版本标签镜像: ${{ env.REPO }}:${{ env.VERSION }}" + docker push ${{ env.REPO }}:${{ env.VERSION }} + + echo "推送分支标签镜像: ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }}" + docker push ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }} + + echo "镜像推送完成" + + # 步骤5: 连接服务器拉镜像启动 + - name: 🚀 连接服务器拉镜像启动 + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ env.SSH_HOST }} + username: ${{ env.SSH_USER }} + password: ${{ env.SSH_PASSWORD }} + port: ${{ env.SSH_PORT }} + timeout: 300s + command_timeout: 600s + script: | + echo "连接服务器成功,开始部署..." + echo "部署容器名: ${{ env.CONTAINER_NAME }}" + echo "部署路径: ${{ env.DEPLOY_PATH }}" + echo "部署镜像: ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }}" + + # 确保部署目录存在 + mkdir -p ${{ env.DEPLOY_PATH }}/config + mkdir -p ${{ env.DEPLOY_PATH }}/logs + + # 停止并删除旧容器(忽略所有错误) + if docker ps -a | grep -q ${{ env.CONTAINER_NAME }} 2>/dev/null; then + echo "停止旧容器..." + docker stop ${{ env.CONTAINER_NAME }} >/dev/null 2>&1 || true + echo "等待容器完全停止..." + sleep 5 + + echo "删除旧容器..." + # 静默删除,完全忽略错误输出 + docker rm ${{ env.CONTAINER_NAME }} >/dev/null 2>&1 || true + sleep 2 + + # 如果仍然存在,尝试强制删除(静默) + if docker ps -a | grep -q ${{ env.CONTAINER_NAME }} 2>/dev/null; then + echo "尝试强制删除..." + docker rm -f ${{ env.CONTAINER_NAME }} >/dev/null 2>&1 || true + sleep 3 + fi + + echo "容器清理完成,继续部署..." + fi + + # 拉取最新分支镜像 + echo "拉取镜像: ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }}..." + docker pull ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }} + + # 启动新容器 + echo "启动新容器..." + cd ${{ env.DEPLOY_PATH }} + docker run -d \ + --name ${{ env.CONTAINER_NAME }} \ + --restart unless-stopped \ + --network host \ + -v ./config/ppanel.yaml:/app/etc/ppanel.yaml \ + -v ./logs:/app/logs \ + ${{ env.REPO }}:${{ env.DOCKER_TAG_SUFFIX }} + + # 检查容器状态 + sleep 5 + if docker ps | grep -q ${{ env.CONTAINER_NAME }}; then + echo "✅ 容器启动成功" + else + echo "❌ 容器启动失败" + docker logs ${{ env.CONTAINER_NAME }} + exit 1 + fi + + # 步骤6: TG通知 (成功) + - name: 📱 发送成功通知到Telegram + if: success() + uses: appleboy/telegram-action@master + with: + token: ${{ env.TG_BOT_TOKEN }} + to: ${{ env.TG_CHAT_ID }} + message: | + ✅ 部署成功! + + 📦 项目: ${{ github.repository }} + 🌿 分支: ${{ github.ref_name }} + 📝 提交: ${{ github.sha }} + 👤 提交者: ${{ github.actor }} + 🕐 时间: ${{ github.event.head_commit.timestamp }} + + 🚀 服务已成功部署到生产环境 + parse_mode: Markdown + + # 步骤5: TG通知 (失败) + - name: 📱 发送失败通知到Telegram + if: failure() + uses: appleboy/telegram-action@master + with: + token: ${{ env.TG_BOT_TOKEN }} + to: ${{ env.TG_CHAT_ID }} + message: | + ❌ 部署失败! + + 📦 项目: ${{ github.repository }} + 🌿 分支: ${{ github.ref_name }} + 📝 提交: ${{ github.sha }} + 👤 提交者: ${{ github.actor }} + 🕐 时间: ${{ github.event.head_commit.timestamp }} + + ⚠️ 请检查构建日志获取详细信息 + parse_mode: Markdown + \ No newline at end of file