跟哥们儿撸串吹牛聊聊怎么让SpringBoot自己"跑"上服务器
SpringBoot自动化部署:让代码自己"飞"上服务器,我躺平!
兄弟,你是不是也这样:代码写爽了,一打包部署就头大?mvn clean package
,找那个该死的jar包,scp
上传,ssh
连上去,ps -ef | grep java
找老进程,kill -9
送走它,在nohup java -jar
...一套组合拳下来,咖啡都凉了!烦不烦? 今天教你用GitHub的免费劳动力(GitHub Actions),让代码自己打包、自己上传、自己重启 !你只需要干一件事:git push
!然后?然后你就可以刷会儿短视频等结果了,贼香!
为啥要搞自动化?懒是第一生产力!
- 省事儿! 告别重复劳动,你的时间很值钱(至少比咖啡值钱吧?)。
- 少犯错! 手滑输错个命令、传错个文件?不存在的!机器比你靠谱(在重复劳动上)。
- 稳如老狗! 每次部署的步骤、环境一模一样,再也不会出现"在我机器上好好的"这种玄学问题。
- 心里有谱! 推完代码,立马就能在GitHub上看到是成了还是挂了,挂了也能马上知道为啥,不用抓瞎。
神器登场:GitHub Actions(免费的!)
这玩意儿是GitHub自带的,跟你代码仓库天生一对。简单说,就是你写个"菜谱"(YAML配置文件),告诉它:"嘿,哥们,当我往main分支推代码时,你按这个步骤帮我跑一下"。它就乖乖地在GitHub提供的"厨房"(虚拟机)里给你干活儿,干完还能告诉你结果。重点是,个人小项目用,免费!
实战开整!让你的SpringBoot App自己"飞"
场景: 你有个贼拉酷的SpringBoot项目(叫awesome-app
吧),用Maven管的,最终要部署到你那台吃灰的Linux服务器(假设IP是111.222.333.444
,用户叫deployer
)。
第一步:服务器上给GitHub Actions发个"接头暗号"(SSH密钥)
-
登服务器,搞密钥:
bashssh [email protected] # 连上你的宝刀服务器 ssh-keygen -t rsa -b 4096 -C "github-actions-deploy" -f ~/.ssh/github-actions
回车回车再回车(别设密码,省事儿)。生成了俩文件:
github-actions
(私钥,宝贝!)和github-actions.pub
(公钥)。 -
告诉服务器:"这公钥是好人!":
bashcat ~/.ssh/github-actions.pub >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys # 权限很重要!
这就相当于把公钥加进了服务器的"VIP通行证"名单。
-
把私钥"藏"进GitHub(千万别泄露!):
- 打开你项目的GitHub页面。
- 点
Settings
->Secrets and variables
->Actions
->New repository secret
。 - Name:
SERVER_SSH_KEY
(名字好记就行) - Value: 把
github-actions
文件里的所有内容(从-----BEGIN OPENSSH PRIVATE KEY-----
到-----END OPENSSH PRIVATE KEY-----
) 全选、复制、粘贴进去!一点别落! - 再新建两个Secret:
SERVER_IP
:111.222.333.444
(你服务器的IP)SERVER_USER
:deployer
(你登录服务器的用户名)
第二步:项目里放"菜谱"(Workflow配置文件)
- 在你SpringBoot项目的根目录 下,新建文件夹:
.github/workflows/
(注意前面有个点!)。 - 在这个文件夹里,新建一个文件,比如叫
deploy-awesome-app.yml
。 - 核心"菜谱"来了! 把下面的代码复制进去,记得看注释按你的情况改:
yaml
name: 自动构建部署Awesome App # 名字可以随便取
on:
push:
branches: [ "main" ] # 重点!只有推送到main分支才触发。用master的改成master
jobs:
build-deploy:
runs-on: ubuntu-latest # GitHub提供的Ubuntu厨房
steps:
# 1. 把代码从冰箱(仓库)里拿出来
- name: 检出代码
uses: actions/checkout@v4
# 2. 准备好Java环境(JDK 17示例)
- name: 装JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin' # 或者 'corretto', 'zulu' 都行
# 3. Maven打包!(跳过测试,赶时间!生产记得去掉 -DskipTests!)
- name: Maven 打包
run: mvn -B clean package -DskipTests # -B 意思"别啰嗦,安静打包"
# 4. 让GitHub Actions "厨房" 连上你的服务器,把jar包传过去并启动!
- name: SSH 部署到服务器
uses: appleboy/[email protected] # 这是一个SSH插件,挺好用
with:
host: ${{ secrets.SERVER_IP }} # 用之前藏的服务器IP
username: ${{ secrets.SERVER_USER }} # 用之前藏的用户名
key: ${{ secrets.SERVER_SSH_KEY }} # 用之前藏的私钥(接头暗号)
script: | # 在服务器上执行的一连串命令,看好了!
# 找到刚打好的jar包(名字根据你的项目变!)
# 打开你本地的 target 文件夹,看看jar包叫啥!这是最容易翻车的地方!
JAR_PATH="/home/github/workspace/target/awesome-app-*.jar" # GitHub Actions 里项目的工作路径
APP_NAME="awesome-app" # 给你的应用起个名,方便管理
DEPLOY_DIR="/home/deployer/apps/$APP_NAME" # 服务器上放app的目录,自己定!
echo "===== 准备起飞! ====="
# 1. 在服务器上创建部署目录(没有就建)
mkdir -p $DEPLOY_DIR
echo "创建/确认目录: $DEPLOY_DIR !"
# 2. 停掉老服务 (粗暴版,生产建议用systemd)
echo "寻找并干掉老进程..."
pkill -f "java -jar $DEPLOY_DIR/$APP_NAME.jar" || echo "没找到老进程,可能是第一次?问题不大!"
# 3. 把新鲜出炉的jar包从GitHub厨房复制到服务器
echo "正在空投jar包..."
scp -o StrictHostKeyChecking=no $JAR_PATH $DEPLOY_DIR/$APP_NAME.jar
echo "jar包空投成功!落点: $DEPLOY_DIR/$APP_NAME.jar"
# 4. 启动新服务!(后台运行,日志输出到文件)
echo "点火!启动新服务..."
cd $DEPLOY_DIR
nohup java -jar $APP_NAME.jar > $APP_NAME.log 2>&1 &
# 5. 喘口气,等几秒看看启动没
echo "等5秒,看看发动机转起来没..."
sleep 5
if pgrep -f "java -jar $APP_NAME.jar" > /dev/null; then
echo "启动成功!进程活着呢!可以去访问了!"
echo "日志文件在这: $DEPLOY_DIR/$APP_NAME.log (万一抽风了记得看这里)"
else
echo "启动好像失败了!赶紧看日志救命: $DEPLOY_DIR/$APP_NAME.log"
exit 1 # 告诉GitHub Actions这一步失败了
fi
echo "===== 部署完成!! ====="
重点盯防区(最容易翻车的地方!)
branches: [ "main" ]
: 你开发用哪个分支?main
还是master
?改成你用的!java-version: '17'
: 你项目用啥JDK?8?11?17?21?必须一致!mvn ... -DskipTests
:-DskipTests
跳过了测试!正式上线前务必去掉它,让测试跑起来! 这是为了演示快。JAR_PATH
和APP_NAME
: 重中之重!- 打开你本地项目打完包后的
target
文件夹,看清楚生成的jar包全名是啥! 是awesome-app-0.0.1-SNAPSHOT.jar
?还是awesome-app.jar
?把/home/github/workspace/target/awesome-app-*.jar
里的awesome-app-*.jar
替换成你实际 的jar包名字模式。可以用*
通配符匹配版本号。 APP_NAME
起个简短好记的名字,比如你的项目名,后面停进程、看日志都用它。
- 打开你本地项目打完包后的
DEPLOY_DIR
: 在服务器上你想把应用放哪儿?/home/deployer/apps/
只是个例子,确保deployer
用户对这个目录有读写执行 权限!mkdir -p
会帮你建目录。- 启停服务 (
pkill
&nohup
): 这是最简单粗暴的方式。生产环境强烈建议用systemd
写个服务文件! (sudo systemctl restart yourapp.service
多优雅多稳!) 这里先用nohup
顶一下。
见证奇迹的时刻:推代码,看它飞!
- 把你改好的代码(特别是那个
.github/workflows/deploy-awesome-app.yml
文件)git add .
,git commit -m "加上了自动部署!"
,然后git push origin main
(或者你的分支名)。 - 立马上GitHub,进你的项目,点顶上的
Actions
标签。 - 你会看到一个叫"自动构建部署Awesome App"的任务跑起来了!点进去可以实时围观日志输出,跟看直播似的。
- 如果满屏绿勾并且看到 "部署完成!": 恭喜!你的代码已经自己"飞"上去跑起来了!赶紧打开浏览器访问你的服务试试!
- 如果出现了刺眼的红叉: 莫慌!点开失败的任务,仔细看日志! 翻车点通常就那几个:
- 私钥格式不对/复制少了: 检查GitHub Secrets里
SERVER_SSH_KEY
是不是复制了完整的 私钥内容(包括-----BEGIN...
和-----END...
)。 - 服务器路径权限不足: 检查
DEPLOY_DIR
,确保SERVER_USER
用户能读写执行。mkdir -p
报错多半是这。 - Jar包路径/名字不对!: 老生常谈!100%确认
JAR_PATH
设置对了!看日志里scp那一步报的啥错。 - 端口冲突/启动失败: 看服务器上
$DEPLOY_DIR/$APP_NAME.log
日志文件!是不是端口被占了?数据库连不上?依赖缺失? - 服务器防火墙/安全组: 确保服务器开放了你的应用端口和SSH端口(22)!
- 私钥格式不对/复制少了: 检查GitHub Secrets里
搞定了基础版?还能更骚!
- 分环境部署: 推
dev
分支自动部署到测试环境,打v1.0
标签部署到生产环境。配置不同的workflow文件或者用if
条件判断分支/tag就行。 - 通知小能手: 部署成功/失败,自动给你发个邮件、Slack消息或者钉钉通知。Action市场有现成的插件。
- 玩Docker: 在Action里
docker build
+docker push
把你的应用打成镜像,推到Docker Hub或者私仓。服务器上docker pull
+docker run
。更现代! - 数据库迁移: 部署前,在服务器上自动跑Flyway或Liquibase脚本更新数据库。
安全提示: 那个
SERVER_SSH_KEY
权限很大!管好你的GitHub仓库权限,别随便给人写权限。定期换换密钥更安全。生产环境强烈建议用权限更小的专用部署用户,并且用systemd
管理服务!