使用GitHub Actions实现Spring Boot项目的自动化部署
使用GitHub Actions实现Spring Boot项目的自动化部署
在现代开发流程中,持续集成与持续部署(CI/CD)已成为常态。借助GitHub Actions可以轻松实现自动化流程,包括代码构建、测试、镜像打包、上传Docker镜像到云服务、部署通知等操作。本文将详细介绍如何使用GitHub Actions完成Spring Boot项目的自动部署。
项目背景
我们有一个使用Spring Boot框架的项目,目标是:
- 使用Maven构建项目。
- 使用Docker镜像打包。
- 推送镜像到阿里云容器镜像服务(Aliyun Container Registry)。
- 通知服务器通过WebHook请求,完成自动化更新。
本文将通过创建GitHub Actions工作流文件(YAML)来实现完整的自动化流程。
准备工作
在实现自动化流程之前,请确保:
- 项目代码已托管在GitHub仓库。
- 已设置阿里云容器镜像服务账号并获取镜像仓库用户名和密码。
- 确保阿里云容器镜像服务支持镜像推送。
- 创建GitHub仓库Secrets:
- ALIYUN_PASSWORD:阿里云容器镜像服务密码。
步骤一:创建GitHub Actions Workflow文件
我们将在项目的.github/workflows文件夹中创建spring-publish.yml文件。这是GitHub Actions的工作流定义文件。
文件路径如下:
<仓库根目录>/
.github/
workflows/
spring-publish.yml
工作流文件内容
name: Deploy Spring Boot Application
# 我这里仅需要PR合并时执行CI
on:
pull_request:
branches:
- master
# 支持手动触发
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
# 提取短哈希并设置为环境变量
- name: Set short SHA
run: echo "SHORT_SHA=$(echo $GITHUB_SHA | cut -c1-6)" >> $GITHUB_ENV
# 克隆代码
- name: Checkout code
uses: actions/checkout@v2
# 设置JDK 20环境
- name: Set up JDK 20
uses: actions/setup-java@v2
with:
java-version: '20'
distribution: 'zulu'
# 缓存Maven依赖
- name: Cache Maven dependencies
uses: actions/cache@v2
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
# Maven构建
- name: Build with Maven
run: mvn clean package -DskipTests
# 构建Docker镜像
- name: Build Docker image
run: |
docker build -t 这里填你的阿里云镜像:${{ env.SHORT_SHA }} .
# 登录阿里云Docker仓库
- name: Log in to Aliyun Docker Registry
uses: docker/login-action@v2
with:
username: 阿里云用户名
password: ${{ secrets.ALIYUN_PASSWORD }}
registry: 你的阿里云仓库地址
# 推送镜像到阿里云镜像仓库
- name: Push Docker image to Aliyun Registry
run: |
docker tag 你的tag信息
docker push 你的镜像信息
# 通知服务器更新
- name: Notify server to update Docker image
run: |
curl -k -X POST "这填你的webhook地址¶m=${{ env.SHORT_SHA }}"
工作流关键步骤解析
1. 提取短哈希值
- name: Set short SHA
run: echo "SHORT_SHA=$(echo $GITHUB_SHA | cut -c1-6)" >> $GITHUB_ENV
我们提取github.sha的前6位作为短哈希(SHORT_SHA),用于标识镜像标签和通知信息。
2. 克隆代码
- name: Checkout code
uses: actions/checkout@v2
actions/checkout是用于克隆仓库代码的标准步骤。
3. 设置JDK环境
- name: Set up JDK 20
uses: actions/setup-java@v2
with:
java-version: '20'
distribution: 'zulu'
确保Java环境为Spring Boot项目构建准备好。
4. 构建Docker镜像
docker build -t 镜像信息:${{ env.SHORT_SHA }} .
使用Dockerfile构建镜像,并用短哈希作为镜像标签。
5. 登录到阿里云容器镜像服务
uses: docker/login-action@v2
安全地通过username和password登录到阿里云镜像仓库。
6. 推送镜像
docker push 镜像信息:${{ env.SHORT_SHA }}
将镜像标记为短哈希并推送到镜像服务。
7. 通知服务更新
curl -k -X POST "webhook地址¶m=${{ env.SHORT_SHA }}"
推送HTTP请求到指定的服务端,用短哈希值通知服务器进行镜像更新。
Secrets设置
在GitHub仓库的Settings > Secrets and variables > Actions中添加以下Secret:
Name | Value |
---|---|
ALIYUN_PASSWORD | 阿里云容器镜像服务密码 |
流程触发方式
- on: pull_request:当有代码合并请求(PR)提交到master分支时触发。
- on: workflow_dispatch:手动触发。
创建WebHook
WebHook用于通知服务器进行更新,我这里用的是宝塔面板,在软件商店中安装一个宝塔WebHook的插件
然后在编辑里面编译Webhook执行的脚本,我这里举个例子:
#!/bin/bash
# 配置参数
DOCKER_REGISTRY="你的docker地址"
DOCKER_IMAGE="镜像名"
DOCKER_USERNAME="阿里云账号名"
DOCKER_PASSWORD="密码" # 替换为真实密码
CONTAINER_NAME="容器名"
# 端口映射规则,自行调整
HOST_PORT=1001
CONTAINER_PORT=48080
LOG_FILE="/www/webhook/deploy.log"
# 创建日志目录(如果不存在)
mkdir -p "$(dirname "$LOG_FILE")"
# 开始记录日志
echo "$(date '+%Y-%m-%d %H:%M:%S') - Starting deployment..." >> "$LOG_FILE"
# 检查是否传入版本号,如果没有则使用latest
VERSION=$1
echo "版本 : $1"
if [ -z "$VERSION" ]; then
VERSION="latest"
fi
echo "$(date '+%Y-%m-%d %H:%M:%S') - Using version: $VERSION" >> "$LOG_FILE"
# 登录Docker Registry
echo "$(date '+%Y-%m-%d %H:%M:%S') - Logging into Docker Registry..." >> "$LOG_FILE"
docker login $DOCKER_REGISTRY -u $DOCKER_USERNAME -p $DOCKER_PASSWORD >> "$LOG_FILE" 2>&1
if [ $? -ne 0 ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') - Docker login failed." >> "$LOG_FILE"
exit 1
fi
# 拉取最新镜像
echo "$(date '+%Y-%m-%d %H:%M:%S') - Pulling Docker image: $DOCKER_IMAGE:$VERSION" >> "$LOG_FILE"
docker pull $DOCKER_REGISTRY/$DOCKER_IMAGE:$VERSION >> "$LOG_FILE" 2>&1
if [ $? -ne 0 ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') - Failed to pull Docker image." >> "$LOG_FILE"
exit 1
fi
# 停止旧容器
echo "$(date '+%Y-%m-%d %H:%M:%S') - Stopping old container (if exists)..." >> "$LOG_FILE"
docker stop $CONTAINER_NAME >> "$LOG_FILE" 2>&1 || true
# 删除旧容器
echo "$(date '+%Y-%m-%d %H:%M:%S') - Removing old container (if exists)..." >> "$LOG_FILE"
docker rm $CONTAINER_NAME >> "$LOG_FILE" 2>&1 || true
# 启动新容器
echo "$(date '+%Y-%m-%d %H:%M:%S') - Starting new container..." >> "$LOG_FILE"
docker run -d --network=host -e TZ=Asia/Shanghai --name $CONTAINER_NAME -p $HOST_PORT:$CONTAINER_PORT $DOCKER_REGISTRY/$DOCKER_IMAGE:$VERSION >> "$LOG_FILE" 2>&1
if [ $? -ne 0 ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') - Failed to start new container." >> "$LOG_FILE"
exit 1
fi
# 部署完成
echo "$(date '+%Y-%m-%d %H:%M:%S') - Deployment completed successfully." >> "$LOG_FILE"
exit 0
测试
手动触发测试
检查所有的任务是否全部完成
可以看到我这里任务全部完成
服务器也已经成功显示docker正在运行
总结
通过上述配置,你可以:
- 使用GitHub Actions构建Docker镜像。
- 通过webhook触发部署流程。
- Docker完成自更新。
这样能有效解耦GitHub Actions和实际的服务器部署流程,提升整体可控性和安全性。🚀