GitHub Actions CI/CD 工作流配置说明
工作流列表
| 工作流 | 说明 | 文档 |
|---|---|---|
| Docker Build and Deploy | API 镜像构建与部署 | 见下文 |
| Android Release Build | Android APK 构建与发布 | 见下文 |
| App Expo Deploy | app-expo Web 构建与发布 | docs/app-expo-deploy.md |
概述
本工作流实现了自动化的 Docker 镜像构建和部署流程:
- 构建阶段:当代码推送到指定分支时,自动构建 Docker 镜像
- 推送阶段:将构建好的镜像推送到阿里云容器镜像服务(ACR)
- 部署阶段:通过 SSH 连接到远程服务器,拉取最新镜像并重建容器
工作流触发条件
- 推送到
main、master或develop分支 - 仅当
api/目录或.github/workflows/目录有变更时触发 - 支持手动触发(workflow_dispatch)
配置步骤
1. 配置 GitHub Secrets
在 GitHub 仓库设置中添加以下 Secrets:
必需配置
-
SSH_PRIVATE_KEY: SSH 私钥,用于连接到远程服务器
# 生成 SSH 密钥对(如果还没有) ssh-keygen -t ed25519 -C "github-actions" # 将私钥添加到 GitHub Secrets cat ~/.ssh/id_ed25519 # 复制内容到 SSH_PRIVATE_KEY # 将公钥添加到远程服务器的 ~/.ssh/authorized_keys cat ~/.ssh/id_ed25519.pub | ssh user@your-server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys" -
SSH_USER: SSH 用户名(例如:
root、ubuntu、deploy) -
SSH_HOST: 远程服务器 IP 地址或域名(例如:
192.168.1.100、example.com)
阿里云容器镜像服务配置(必需)
- ALIYUN_CR_USERNAME: 阿里云容器镜像服务用户名(例如:
zaikunxu) - ALIYUN_CR_PASSWORD: 阿里云容器镜像服务密码
可选配置
- SSH_PORT: SSH 端口(默认:
22) - DEPLOY_PATH: 远程服务器上的部署目录(默认:
/opt/life-echo)
2. 容器镜像仓库配置
本工作流使用**阿里云容器镜像服务(ACR)**作为镜像仓库。
镜像地址
- 镜像仓库地址:
crpi-u2903xccyzd6nqnc.cn-shanghai.personal.cr.aliyuncs.com - 命名空间:
huaga - 镜像名称:
lifecho-api - 完整镜像路径:
crpi-u2903xccyzd6nqnc.cn-shanghai.personal.cr.aliyuncs.com/huaga/lifecho-api:latest
配置说明
工作流已配置为使用阿里云容器镜像服务,无需修改工作流文件。只需在 GitHub Secrets 中配置:
ALIYUN_CR_USERNAME: 阿里云容器镜像服务用户名ALIYUN_CR_PASSWORD: 阿里云容器镜像服务密码
在远程服务器上配置 Docker 登录
确保远程服务器可以拉取私有镜像,需要在远程服务器上执行:
docker login crpi-u2903xccyzd6nqnc.cn-shanghai.personal.cr.aliyuncs.com \
--username=zaikunxu \
--password=57ucV,g4LF2cqm8
或者将登录信息添加到工作流的部署步骤中(已自动配置)。
3. 远程服务器准备
确保远程服务器已安装:
- Docker
- Docker Compose
# 安装 Docker(Ubuntu/Debian)
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# 安装 Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
4. 首次部署准备
在远程服务器上创建部署目录:
mkdir -p /opt/life-echo/api
确保 SSH 用户可以访问该目录并执行 Docker 命令。
工作流执行流程
构建阶段(build-and-push)
- 检出代码
- 设置 Docker Buildx
- 登录到容器镜像仓库
- 提取元数据(标签、标签)
- 构建并推送 Docker 镜像
部署阶段(deploy)
- 设置 SSH 连接
- 登录到容器镜像仓库(在远程服务器上)
- 拉取最新镜像
- 停止现有容器
- 更新 docker-compose.yml 中的镜像标签
- 启动新容器
- 清理旧镜像
- 验证部署状态
镜像标签规则
main/master分支 →latest- 其他分支 → 使用分支名作为标签
- 同时会生成基于 commit SHA 的标签
故障排查
1. SSH 连接失败
- 检查
SSH_PRIVATE_KEY是否正确配置 - 确认远程服务器的 SSH 服务正在运行
- 验证 SSH 公钥已添加到远程服务器的
~/.ssh/authorized_keys
2. Docker 登录失败
- 检查
ALIYUN_CR_USERNAME和ALIYUN_CR_PASSWORD是否正确配置 - 确认阿里云容器镜像服务的账号密码是否正确
- 检查远程服务器是否可以访问阿里云容器镜像服务
3. 镜像拉取失败
- 确认远程服务器可以访问容器镜像仓库
- 检查镜像标签是否正确
- 验证网络连接
4. 容器启动失败
- 检查 docker-compose.yml 文件是否正确
- 查看容器日志:
docker-compose logs - 确认环境变量配置正确
手动触发
可以通过 GitHub Actions 界面手动触发工作流:
- 进入仓库的 Actions 标签页
- 选择 "Docker Build and Deploy" 工作流
- 点击 "Run workflow" 按钮
自定义配置
修改触发分支
编辑 .github/workflows/docker-build-deploy.yml:
on:
push:
branches:
- your-branch-name
修改镜像名称
编辑工作流文件中的 IMAGE_NAME 和 REGISTRY_NAMESPACE 环境变量:
env:
IMAGE_NAME: your-image-name
REGISTRY_NAMESPACE: your-namespace
修改部署路径
在 GitHub Secrets 中设置 DEPLOY_PATH,或直接修改工作流文件中的默认值。
注意事项
- 安全性:确保 SSH 私钥和密码等敏感信息只存储在 GitHub Secrets 中,不要提交到代码仓库
- 权限:确保 SSH 用户在远程服务器上有执行 Docker 命令的权限
- 备份:部署前会自动备份 docker-compose.yml 文件(
.bak后缀) - 回滚:如果部署失败,可以使用备份文件恢复
相关文件
- 工作流文件:
.github/workflows/docker-build-deploy.yml - Dockerfile:
api/Dockerfile - Docker Compose:
api/docker-compose.yml
Android Release 工作流
概述
自动构建生产环境签名 APK 并发布到 GitHub Releases:
- 构建阶段:编译 Release APK,使用生产签名配置
- 发布阶段:创建 GitHub Release,将 APK 作为附件上传
工作流触发条件
- Tag 推送:推送
v*格式的标签时自动触发(如v1.0.0、v1.2.3-beta) - 手动触发:通过 GitHub Actions 界面手动触发,可选指定版本号
配置步骤
1. 配置 GitHub Secrets
在 GitHub 仓库设置中添加以下 Secrets:
| Secret | 说明 | 示例 |
|---|---|---|
ANDROID_KEYSTORE_BASE64 |
keystore 文件的 Base64 编码 | 见下方生成方法 |
ANDROID_KEY_ALIAS |
密钥别名 | suiyueshishu |
ANDROID_KEY_PASSWORD |
密钥密码 | |
ANDROID_STORE_PASSWORD |
keystore 密码 |
生成 ANDROID_KEYSTORE_BASE64
# 在本地项目 app-android 目录下执行
base64 -i release-keystore.jks | pbcopy # macOS,结果已复制到剪贴板
# Linux
base64 -w 0 release-keystore.jks
将输出内容粘贴到 GitHub Secrets 的 ANDROID_KEYSTORE_BASE64 中。
2. 版本号管理
- Tag 触发:从 tag 名自动提取版本号(如
v1.0.0→versionName = "1.0.0") - 手动触发:使用输入的
version_name,或使用build.gradle.kts中的默认值 - versionCode:自动使用
GITHUB_RUN_NUMBER递增
3. 发布流程
方式一:通过 Tag 自动发布
# 打标签并推送
git tag v1.0.0
git push origin v1.0.0
# 或者一步完成
git tag v1.0.0 && git push origin v1.0.0
工作流将自动:
- 构建签名 Release APK
- 上传 APK 为 GitHub Artifact
- 创建 GitHub Release(附带 APK 和自动生成的更新日志)
方式二:手动触发
- 进入仓库的 Actions 标签页
- 选择 "Android Release Build" 工作流
- 点击 "Run workflow" 按钮
- (可选)填写版本号
- 点击 "Run workflow"
手动触发时仅构建 APK 并上传为 Artifact,不会创建 GitHub Release。
工作流执行流程
- 检出代码(完整历史)
- 确定版本号(Tag / 手动输入 / build.gradle.kts 默认值)
- 设置 JDK 17 + Gradle 缓存
- 解码签名 keystore + 生成 keystore.properties
- 覆盖 build.gradle.kts 中的版本号
- 执行
./gradlew assembleRelease - 上传 APK 为 Artifact(保留 30 天)
- (Tag 触发时)生成 Release Notes 并创建 GitHub Release
APK 命名规则
APK 文件命名格式:岁月时书_v{版本号}_release.apk
示例:岁月时书_v1.0.0_release.apk
故障排查
1. 签名失败
- 检查
ANDROID_KEYSTORE_BASE64是否正确生成(不能有换行或空格) - 确认
ANDROID_KEY_ALIAS、ANDROID_KEY_PASSWORD、ANDROID_STORE_PASSWORD与 keystore 匹配
2. 构建失败
- 检查 Actions 日志中的 Gradle 错误输出
- 确认本地
./gradlew assembleRelease可以成功
3. Release 创建失败
- 确认工作流有
contents: write权限 - 检查 Tag 名称是否以
v开头