CentOS7 + 宝塔 Nginx + Java Jar:GitHub Actions 自动部署步骤
摘要本文详细介绍了使用 GitHub Actions 实现前后端项目自动化部署的完整流程。从服务器环境准备、SSH 密钥生成、GitHub Secrets 配置到部署文件编写、首次部署和日常发布提供了全栈部署的一站式解决方案。文章包含具体的脚本示例、配置步骤和故障排查方法帮助开发者快速搭建自动化部署流水线。一、服务器准备确认前端站点目录、管理端站点目录、后端目录已存在用户端/www/wwwroot/www.mocsim.com管理端/www/wwwroot/admin.mocsim.com后端/opt确认服务器已安装 Java 17可用命令java -version确认后端 jar 名称为xxxx-xxxx-1.0.0.jar将restart-backend.sh放到/opt/restart-backend.sh#!/bin/bash # 示例后端重启脚本可直接复制后按自己项目改 jar 名 # 建议放到服务器后端目录例如: /opt/my-app/restart-backend.sh # 与 jar 同目录例如: /opt/my-app/my-app-1.0.0.jar # 用法: bash /opt/my-app/restart-backend.sh # # Windows 传到 Linux 后若报 set: pipefail先执行: # sed -i s/\r$// restart-backend.sh set -euo pipefail APP_DIR$(cd $(dirname $0) pwd) 示例 jar 名按实际修改 JAR_NAME${JAR_NAME:-my-app-1.0.0.jar} JAR_PATH$APP_DIR/$JAR_NAME PID_FILE$APP_DIR/app.pid LOG_FILE$APP_DIR/app.log JAVA_BIN${JAVA_BIN:-java} 默认生产环境可覆盖: SPRING_PROFILEtest bash restart-backend.sh SPRING_PROFILE${SPRING_PROFILE:-prod} if [[ ! -f $JAR_PATH ]]; then echo ERROR: jar not found: $JAR_PATH exit 1 fi stop_old() { if [[ -f $PID_FILE ]]; then OLD_PID$(cat $PID_FILE || true) if [[ -n ${OLD_PID} ]] kill -0 $OLD_PID 2/dev/null; then echo Stopping pid $OLD_PID ... kill $OLD_PID || true for _ in $(seq 1 20); do kill -0 $OLD_PID 2/dev/null || break sleep 0.5 done if kill -0 $OLD_PID 2/dev/null; then echo Force kill $OLD_PID kill -9 $OLD_PID || true fi fi rm -f $PID_FILE fi pkill -f $JAR_NAME 2/dev/null || true sleep 1 } start_new() { echo Starting $JAR_PATH (profile$SPRING_PROFILE) ... cd $APP_DIR nohup $JAVA_BIN -jar $JAR_NAME --spring.profiles.active$SPRING_PROFILE $LOG_FILE 21 echo $! $PID_FILE echo Started pid $(cat $PID_FILE), log: $LOG_FILE } stop_old start_new echo Backend restart done.执行chmod x /opt/restart-backend.sh sed -i s/\r$// /opt/restart-backend.sh手动测试重启bash /opt/restart-backend.sh tail -n 50 /opt/app.log确认日志出现The following 1 profile is active: prod新建 .github/workflows/deploy.yml 示例如下# 示例GitHub Actions 自动部署可直接复制后按自己项目改路径 文件建议放在仓库.github/workflows/deploy.yml 需要在 GitHub → Settings → Secrets and variables → Actions 配置 DEPLOY_HOST 服务器公网 IP DEPLOY_USER SSH 用户如 root DEPLOY_PORT SSH 端口如 22 DEPLOY_SSH_KEY 部署用私钥全文 FRONT_REMOTE_PATH 用户端站点目录如 /www/wwwroot/www.example.com ADMIN_REMOTE_PATH 管理端站点目录如 /www/wwwroot/admin.example.com BACKEND_REMOTE_DIR 后端目录如 /opt/my-app name: Deploy on: push: branches: [main] workflow_dispatch: concurrency: group: deploy-production cancel-in-progress: true jobs: build-and-deploy: runs-on: ubuntu-latest env: DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} DEPLOY_USER: ${{ secrets.DEPLOY_USER }} DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }} FRONT_REMOTE_PATH: ${{ secrets.FRONT_REMOTE_PATH }} ADMIN_REMOTE_PATH: ${{ secrets.ADMIN_REMOTE_PATH }} BACKEND_REMOTE_DIR: ${{ secrets.BACKEND_REMOTE_DIR }} steps: - name: Checkout uses: actions/checkoutv4 - name: Setup Node.js uses: actions/setup-nodev4 with: node-version: 20 name: Setup Java uses: actions/setup-javav4 with: distribution: temurin java-version: 17 cache: maven cache-dependency-path: backend/pom.xml 示例用户端前端目录 frontend/web name: Build storefront working-directory: frontend/web run: | if [ -f package-lock.json ]; then npm ci; else npm install; fi npm run build 示例管理端前端目录 frontend/admin name: Build admin working-directory: frontend/admin run: | if [ -f package-lock.json ]; then npm ci; else npm install; fi npm run build 示例后端用 -Pprod 打包产物名为 my-app-1.0.0.jar name: Build backend jar working-directory: backend run: mvn -B -Pprod -DskipTests package name: Prepare SSH run: | set -euo pipefail PORT${DEPLOY_PORT:-22} mkdir -p ~/.ssh echo $DEPLOY_SSH_KEY gt; ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key ssh-keyscan -p $PORT -H $DEPLOY_HOST gt;gt; ~/.ssh/known_hosts 2gt;/dev/null || true echo SSH_PORT$PORT gt;gt; $GITHUB_ENV env: DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} name: Upload storefront run: | RSYNC_SSHssh -i ~/.ssh/deploy_key -p ${SSH_PORT} -o StrictHostKeyCheckingaccept-new 宝塔站点常有受保护的 .user.ini--delete 删不掉会触发 rsync code 23 rsync -avz --delete --exclude.user.ini --exclude.htaccess --exclude.well-known --no-owner --no-group --no-perms -e $RSYNC_SSH frontend/web/dist/ ${DEPLOY_USER}${DEPLOY_HOST}:${FRONT_REMOTE_PATH}/ name: Upload admin run: | RSYNC_SSHssh -i ~/.ssh/deploy_key -p ${SSH_PORT} -o StrictHostKeyCheckingaccept-new rsync -avz --delete --exclude.user.ini --exclude.htaccess --exclude.well-known --no-owner --no-group --no-perms -e $RSYNC_SSH frontend/admin/dist/ ${DEPLOY_USER}${DEPLOY_HOST}:${ADMIN_REMOTE_PATH}/ name: Upload backend jar and restart script run: | rsync -avz -e ssh -i ~/.ssh/deploy_key -p ${SSH_PORT} -o StrictHostKeyCheckingaccept-new backend/target/my-app-1.0.0.jar deploy/restart-backend.sh ${DEPLOY_USER}${DEPLOY_HOST}:${BACKEND_REMOTE_DIR}/ ssh -i ~/.ssh/deploy_key -p ${SSH_PORT} -o StrictHostKeyCheckingaccept-new ${DEPLOY_USER}${DEPLOY_HOST} chmod x ${BACKEND_REMOTE_DIR}/restart-backend.sh amp;amp; sed -i s/\r$// ${BACKEND_REMOTE_DIR}/restart-backend.sh name: Restart backend run: | ssh -i ~/.ssh/deploy_key -p ${SSH_PORT} -o StrictHostKeyCheckingaccept-new ${DEPLOY_USER}${DEPLOY_HOST} bash ${BACKEND_REMOTE_DIR}/restart-backend.sh二、生成部署 SSH 密钥在服务器执行mkdir -p ~/.ssh chmod 700 ~/.ssh ssh-keygen -t ed25519 -C github-deploy -f ~/.ssh/mocbase_deploy -N cat ~/.ssh/mocbase_deploy.pub ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys ~/.ssh/mocbase_deploy查看私钥稍后填到 GitHub Secretscat ~/.ssh/mocbase_deploy三、配置 GitHub Secrets打开仓库地址https://github.com/你的用户名/你的仓库名/settings/secrets/actions点击New repository secret依次新增以下 7 个NameSecret 示例DEPLOY_HOST服务器公网 IPDEPLOY_USERrootDEPLOY_PORT22DEPLOY_SSH_KEYcat ~/.ssh/mocbase_deploy的完整私钥FRONT_REMOTE_PATH/www/wwwroot/www.xxxxx.comADMIN_REMOTE_PATH/www/wwwroot/xxxx.xxxxx.comBACKEND_REMOTE_DIR/opt示例如下四、仓库部署文件仓库根目录需有示例在服务器准备中.github/workflows/deploy.yml deploy/restart-backend.sh五、提交并首次部署提交并推送git push origin main打开https://github.com/你的用户名/你的仓库名/actions查看Deploy工作流是否成功绿色勾若失败在Upload storefront且提示 connection timed out检查DEPLOY_HOST是否填错公网 IP、安全组/宝塔是否放行 SSH 端口若失败为 rsync code 23确认已排除.user.ini等宝塔文件成功示例六、日常发布本地改完代码后执行git push origin main打开 Actions 查看Deploy是否成功强刷前台和管理端页面验证后端验证grep -i profile is active /opt/app.log | tail -5tail -n 30 /opt/app.log七、说明服务器不需要安装 Maven、Node构建在 GitHub Actions 云端完成服务器只接收产物并重启前端替换静态文件基本无感后端java -jar重启会有短暂中断

相关新闻

esxi网卡直通

esxi网卡直通

ESXI设置网卡直通什么是直通?原理科普白话文解释:1.字面意思,很好理解,就是在虚拟机中,硬件不需要虚拟设备或者软件进行转换,虚拟机直接调用硬件,跟物理机一样。也就是某一个虚拟机,…

2026/7/23 18:16:56阅读更多 →
Tiva TM4C1292 EPI模块地址映射与非阻塞读FIFO机制详解

Tiva TM4C1292 EPI模块地址映射与非阻塞读FIFO机制详解

1. 项目概述与核心价值 在嵌入式系统开发,尤其是基于ARM Cortex-M内核的微控制器项目中,如何高效、可靠地扩展外部存储器和连接高速外设,是提升系统整体性能与功能复杂度的关键。Tiva™ C系列微控制器,特别是像TM4C1292NCZAD这类高…

2026/7/23 18:16:56阅读更多 →
打破文档孤岛:将知识库深度融入DevOps流水线

打破文档孤岛:将知识库深度融入DevOps流水线

在长期的研发效能优化实践中,我们经常会遇到一个极其割裂的场景:需求在Jira或禅道里流转,代码在GitLab里提交,流水线在Jenkins上跑着,而最核心的技术方案、接口文档和复盘报告,却孤零零地躺在Confluence或W…

2026/7/23 18:14:56阅读更多 →
基于GFL_R101_FPN的肠球菌自动检测系统开发

基于GFL_R101_FPN的肠球菌自动检测系统开发

1. 项目背景与核心价值肠球菌检测在医疗诊断、食品安全和环境监测等领域具有重要应用价值。传统检测方法通常依赖人工镜检或培养法,存在耗时长、主观性强等局限性。我们基于GFL_R101_FPN_MS-2x_COCO模型开发的自动检测系统,将目标检测技术引入微生物识别…

2026/7/23 19:37:16阅读更多 →
从思科到软路由:深入理解网络世界的两种维度与身份

从思科到软路由:深入理解网络世界的两种维度与身份

最近刚研究了不少软路由相关的东西,回想起大学课程中有一门和网络工程师相关的思科网络的课程,从RIP协议到OSPF协议,分析网络拓扑图,给交换机路由器敲命令,我还记得那熟悉的命令ip running config,看似它们…

2026/7/23 19:37:16阅读更多 →
为什么你的OpenWrt软路由Web端口修改后无法访问?常见问题排查指南

为什么你的OpenWrt软路由Web端口修改后无法访问?常见问题排查指南

为什么你的OpenWrt软路由Web端口修改后无法访问?常见问题排查指南 最近在折腾软路由的朋友,估计不少人都遇到过这个情况:为了安全或者避开端口冲突,兴冲冲地修改了OpenWrt的Web管理端口,结果保存重启后,浏览器里输入新地址,迎接你的却是一个冷冰冰的“无法访问此网站”…

2026/7/23 19:37:16阅读更多 →
嵌入式系统硬件CRC与向量中断管理:高可靠实时应用的核心技术

嵌入式系统硬件CRC与向量中断管理:高可靠实时应用的核心技术

1. 项目概述与核心价值 在嵌入式系统,尤其是汽车电子、工业控制这类对可靠性要求极高的领域,数据在传输和存储过程中的完整性,以及系统对外部事件的实时响应能力,是决定产品成败的两个基石。前者关乎数据是否正确,后者…

2026/7/23 19:37:16阅读更多 →
DMA控制器原理与应用:从数据搬运到嵌入式系统性能优化

DMA控制器原理与应用:从数据搬运到嵌入式系统性能优化

1. DMA控制器核心价值与设计哲学 在嵌入式系统里,CPU的时间是宝贵的。想象一下,你正在用MCU处理一个实时音频流,每秒钟有数万个采样点需要从ADC搬运到内存缓冲区,然后再进行滤波、编码等运算。如果每个采样点的搬运都让CPU亲自执行…

2026/7/23 19:37:15阅读更多 →
深入解析TI F021 Flash控制器:寄存器配置与诊断模式实战指南

深入解析TI F021 Flash控制器:寄存器配置与诊断模式实战指南

1. F021 Flash控制器:嵌入式存储的“神经中枢” 在嵌入式系统,尤其是汽车电子和工业控制领域,Flash存储器扮演着“非易失性大脑”的角色,负责存储启动代码、应用程序、校准数据和用户配置。然而,直接操作Flash物理阵列…

2026/7/23 19:35:15阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/23 0:56:31阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/23 0:56:31阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 0:56:31阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:00:28阅读更多 →
从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:28阅读更多 →
油泥处理设备哪里能买到

油泥处理设备哪里能买到

油泥处理设备哪里有?这是许多从事油田、炼化、清罐业务的从业者最关心的问题。根据河南三丰环保设备有限公司的行业经验,选购油泥处理设备的核心在于设备能否适配当地环保法规与原料特性,而非单纯看价格。该公司总经理王钦田先生指出&#xf…

2026/7/23 0:00:28阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/22 22:56:18阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/23 18:58:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/23 18:58:18阅读更多 →