name: Build docker and publish run-name: zero-ppanel Docker构建和部署 on: push: branches: - main - dev pull_request: branches: - main - dev env: REPO: ${{ vars.REPO || 'registry.kxsw.us/vpn-server' }} SSH_HOST: ${{ github.ref_name == 'main' && vars.SSH_HOST || vars.DEV_SSH_HOST }} SSH_PORT: ${{ vars.SSH_PORT }} SSH_USER: ${{ vars.SSH_USER }} SSH_PASSWORD: ${{ github.ref_name == 'main' && vars.SSH_PASSWORD || vars.DEV_SSH_PASSWORD }} TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }} TG_CHAT_ID: ${{ secrets.TG_CHAT_ID }} VERSION: ${{ github.sha }} BUILDTIME: ${{ github.event.head_commit.timestamp }} jobs: # ============================================================ # Job 1: 设置环境变量,供后续 jobs 共享 # ============================================================ prepare: runs-on: zero-ppanel-server container: image: node:20 strategy: matrix: # 只有node支持版本号别名 node: ['20.15.1'] outputs: docker_tag: ${{ steps.vars.outputs.docker_tag }} container_suffix: ${{ steps.vars.outputs.container_suffix }} deploy_path: ${{ steps.vars.outputs.deploy_path }} steps: - name: ⚙️ 计算部署变量 id: vars run: | case "${{ github.ref_name }}" in main) echo "docker_tag=latest" >> $GITHUB_OUTPUT echo "container_suffix=" >> $GITHUB_OUTPUT echo "deploy_path=/root/bindbox" >> $GITHUB_OUTPUT ;; dev) echo "docker_tag=dev" >> $GITHUB_OUTPUT echo "container_suffix=-dev" >> $GITHUB_OUTPUT echo "deploy_path=/root/bindbox-dev" >> $GITHUB_OUTPUT ;; *) echo "docker_tag=${{ github.ref_name }}" >> $GITHUB_OUTPUT echo "container_suffix=-${{ github.ref_name }}" >> $GITHUB_OUTPUT echo "deploy_path=/root/vpn_server_other" >> $GITHUB_OUTPUT ;; esac # ============================================================ # Job 2: 并行矩阵构建 5 个服务镜像 # ============================================================ build: runs-on: zero-ppanel-server needs: prepare strategy: fail-fast: false matrix: service: - name: api dockerfile: deploy/Dockerfile.api image_name: zero-ppanel-api - name: admin dockerfile: deploy/Dockerfile.admin image_name: zero-ppanel-admin - name: node dockerfile: deploy/Dockerfile.node image_name: zero-ppanel-node - name: queue dockerfile: deploy/Dockerfile.queue image_name: zero-ppanel-queue - name: scheduler dockerfile: deploy/Dockerfile.scheduler image_name: zero-ppanel-scheduler steps: - name: 📥 下载代码 uses: actions/checkout@v4 - name: Set up Node.js environment # 设置 Node.js 环境 uses: actions/setup-node@v2 with: node-version: '20.15.1' - name: 🔧 安装 Docker CLI run: | set -e export DEBIAN_FRONTEND=noninteractive # 等待 apt 锁释放 for i in $(seq 1 60); do if ! fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; then break; fi echo "等待 apt 锁... ($i/60)"; sleep 5 done apt-get update -y -o Dpkg::Lock::Timeout=300 apt-get install -y -o Dpkg::Lock::Timeout=300 ca-certificates curl gnupg # 安装 Docker 官方 CLI (API >= 1.44) install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg \ | gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] \ https://download.docker.com/linux/debian \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \ > /etc/apt/sources.list.d/docker.list apt-get update -y -o Dpkg::Lock::Timeout=300 apt-get install -y -o Dpkg::Lock::Timeout=300 docker-ce-cli docker-buildx-plugin echo "Docker CLI 版本: $(docker --version)" echo "API 版本: $(docker version --format '{{.Client.APIVersion}}')" - name: 📤 构建并推送 ${{ matrix.service.name }} run: | DOCKER_TAG="${{ needs.prepare.outputs.docker_tag }}" IMAGE_BASE="${{ env.REPO }}/${{ matrix.service.image_name }}" echo "构建服务: ${{ matrix.service.name }}" echo "镜像: ${IMAGE_BASE}" echo "标签: ${DOCKER_TAG} | ${{ env.VERSION }}" docker build \ -f ${{ matrix.service.dockerfile }} \ --platform linux/amd64 \ --build-arg VERSION=${{ env.VERSION }} \ --build-arg BUILDTIME=${{ env.BUILDTIME }} \ -t ${IMAGE_BASE}:${{ env.VERSION }} \ -t ${IMAGE_BASE}:${DOCKER_TAG} \ . docker push ${IMAGE_BASE}:${{ env.VERSION }} docker push ${IMAGE_BASE}:${DOCKER_TAG} echo "✅ ${{ matrix.service.name }} 镜像推送完成" # ============================================================ # Job 3: 部署到服务器 # ============================================================ deploy: runs-on: ario-server needs: [prepare, build] # PR 不触发部署,只有直接推送才部署 if: github.event_name == 'push' steps: - name: 📥 下载代码 (获取 docker-compose.cloud.yml) uses: actions/checkout@v4 - name: 📂 传输 docker-compose.cloud.yml uses: appleboy/scp-action@v0.1.7 with: host: ${{ env.SSH_HOST }} username: ${{ env.SSH_USER }} password: ${{ env.SSH_PASSWORD }} port: ${{ env.SSH_PORT }} source: "deploy/docker-compose.cloud.yml" target: "${{ needs.prepare.outputs.deploy_path }}/" strip_components: 1 - 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: | set -e DEPLOY_PATH="${{ needs.prepare.outputs.deploy_path }}" DOCKER_TAG="${{ needs.prepare.outputs.docker_tag }}" REPO="${{ env.REPO }}" echo "部署目录: ${DEPLOY_PATH}" echo "镜像标签: ${DOCKER_TAG}" cd ${DEPLOY_PATH} # 写入环境变量供 docker-compose 使用 cat > .env <