使用自托管的方式
This commit is contained in:
@@ -1,50 +1,147 @@
|
||||
name: 构建并部署 Spring Boot 应用
|
||||
on: [push]
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
container:
|
||||
image: maven:3.8.6-openjdk-17
|
||||
options: --pull=always
|
||||
|
||||
runs-on: ubuntu-24.04 # 使用更稳定的标签
|
||||
|
||||
runs-on: self-hosted # 使用自托管 Runner
|
||||
|
||||
steps:
|
||||
- name: 检出代码
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: 设置 JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
cache: 'maven'
|
||||
|
||||
- name: 验证环境
|
||||
run: |
|
||||
echo "Runner 工作目录: $(pwd)"
|
||||
echo "Docker 信息:"
|
||||
docker --version
|
||||
docker info
|
||||
echo "Maven 信息:"
|
||||
mvn --version
|
||||
|
||||
- name: 缓存 Maven 依赖
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-maven-
|
||||
|
||||
- name: 使用 Maven 打包
|
||||
run: mvn clean package -DskipTests
|
||||
- name: 运行测试
|
||||
run: mvn test
|
||||
|
||||
- name: 验证构建结果
|
||||
run: ls -la target/*.jar
|
||||
|
||||
- name: 构建 Docker 镜像
|
||||
run: docker build -t light-delivery-app:latest .
|
||||
|
||||
- name: 部署到服务器
|
||||
env:
|
||||
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
SERVER_IP: ${{ secrets.SERVER_IP }}
|
||||
- name: 使用 Jib 构建到本地 Docker
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
echo "$SSH_PRIVATE_KEY" > ~/.ssh/deploy_key
|
||||
chmod 600 ~/.ssh/deploy_key
|
||||
ssh-keyscan $SERVER_IP >> ~/.ssh/known_hosts
|
||||
# 使用 Jib 直接构建到本地 Docker 守护进程
|
||||
# 这会利用 Jib 的分层缓存机制,后续构建会更快
|
||||
mvn compile jib:dockerBuild -DskipTests \
|
||||
-Djib.to.image=light-delivery-app:latest \
|
||||
-Djib.container.ports=8080,8443 \
|
||||
-Djib.container.environment.SPRING_PROFILES_ACTIVE=prod \
|
||||
-Djib.container.jvmFlags=-Xmx512m,-Xms256m
|
||||
|
||||
- name: 验证镜像构建
|
||||
run: |
|
||||
echo "构建的 Docker 镜像:"
|
||||
docker images | grep light-delivery-app
|
||||
echo "镜像详情:"
|
||||
docker inspect light-delivery-app:latest --format='Size: {{.Size}} bytes, Created: {{.Created}}'
|
||||
|
||||
- name: 停止旧容器
|
||||
run: |
|
||||
# 优雅停止旧容器
|
||||
docker stop light-delivery-container 2>/dev/null || echo "没有运行中的容器"
|
||||
docker rm light-delivery-container 2>/dev/null || echo "没有可删除的容器"
|
||||
|
||||
- name: 备份当前镜像(可选)
|
||||
run: |
|
||||
# 为当前运行中的镜像创建备份标签
|
||||
if docker images light-delivery-app:latest --quiet | grep -q .; then
|
||||
BACKUP_TAG="backup-$(date +%Y%m%d-%H%M%S)"
|
||||
docker tag light-delivery-app:latest light-delivery-app:$BACKUP_TAG
|
||||
echo "已创建备份: light-delivery-app:$BACKUP_TAG"
|
||||
fi
|
||||
|
||||
- name: 运行新容器
|
||||
run: |
|
||||
# 创建必要的目录
|
||||
sudo mkdir -p /app/logs
|
||||
sudo mkdir -p /etc/ssl/certs
|
||||
sudo chown $USER:$USER /app/logs 2>/dev/null || true
|
||||
|
||||
ssh -i ~/.ssh/deploy_key root@$SERVER_IP '
|
||||
docker stop light-delivery-container || true
|
||||
docker rm light-delivery-container || true
|
||||
docker run -d \
|
||||
--name light-delivery-container \
|
||||
-p 443:443 -p 80:80 \
|
||||
-v /etc/ssl/certs:/etc/ssl/certs:ro \
|
||||
-e KEY_STORE_PASSWORD="$(cat /etc/ssl/certs/keyStorePass.txt)" \
|
||||
light-delivery-app:latest
|
||||
'
|
||||
echo "启动新容器..."
|
||||
docker run -d \
|
||||
--name light-delivery-container \
|
||||
--restart=unless-stopped \
|
||||
--log-opt max-size=10m \
|
||||
--log-opt max-file=3 \
|
||||
-p 8080:8080 \
|
||||
-p 8443:8443 \
|
||||
-e SPRING_PROFILES_ACTIVE=prod \
|
||||
-e JAVA_OPTS="-Xmx512m -Xms256m -Djava.security.egd=file:/dev/./urandom" \
|
||||
-v /app/logs:/app/logs \
|
||||
-v /etc/ssl/certs:/etc/ssl/certs:ro \
|
||||
-e SERVER_SSL_KEY_STORE_PASSWORD="${{ secrets.KEY_STORE_PASSWORD }}" \
|
||||
light-delivery-app:latest
|
||||
|
||||
- name: 等待应用启动并健康检查
|
||||
run: |
|
||||
echo "等待应用启动..."
|
||||
# 最大重试次数
|
||||
MAX_RETRIES=12
|
||||
RETRY_COUNT=0
|
||||
|
||||
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
|
||||
if curl -f -s http://localhost:8080/actuator/health > /dev/null 2>&1; then
|
||||
echo "✅ 应用健康检查通过"
|
||||
|
||||
# 获取详细的健康信息
|
||||
HEALTH_INFO=$(curl -s http://localhost:8080/actuator/health)
|
||||
echo "健康状态: $HEALTH_INFO"
|
||||
break
|
||||
fi
|
||||
|
||||
RETRY_COUNT=$((RETRY_COUNT + 1))
|
||||
echo "健康检查失败 ($RETRY_COUNT/$MAX_RETRIES),10秒后重试..."
|
||||
sleep 10
|
||||
done
|
||||
|
||||
if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then
|
||||
echo "❌ 应用启动超时,查看日志:"
|
||||
docker logs light-delivery-container --tail 50
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: 清理资源
|
||||
run: |
|
||||
# 清理旧的备份镜像(保留最近5个)
|
||||
echo "清理旧的备份镜像..."
|
||||
docker images light-delivery-app --filter "reference=light-delivery-app:backup-*" \
|
||||
--format "{{.Tag}}\t{{.CreatedAt}}" | \
|
||||
sort -k2 -r | \
|
||||
tail -n +6 | \
|
||||
awk '{print $1}' | \
|
||||
xargs -r -I {} docker rmi light-delivery-app:{} || echo "无需清理"
|
||||
|
||||
# 清理无用镜像和容器
|
||||
docker system prune -f
|
||||
|
||||
- name: 部署完成通知
|
||||
run: |
|
||||
echo "🎉 部署完成!"
|
||||
echo "应用运行在: http://localhost:8080"
|
||||
echo "容器状态: $(docker inspect light-delivery-container --format='{{.State.Status}}')"
|
||||
echo "启动时间: $(docker inspect light-delivery-container --format='{{.State.StartedAt}}')"
|
Reference in New Issue
Block a user