Files
cozsweet-frontend-nextjs/docs/docker-image-ci.md
T

121 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Docker 镜像持续构建与发布
本文档说明 Gitea Actions 中 Docker 镜像构建、发布与 SSH 部署 workflow 的使用方式。对应脚本为 [.gitea/workflows/docker-image.yml](../.gitea/workflows/docker-image.yml)。
## 职责划分
当前持续集成拆成两条链路:
| Workflow | 触发时机 | 职责 |
| --- | --- | --- |
| `.gitea/workflows/ci.yml` | `dev``main``test` push / PR | 安装依赖、Lint、单元测试、Next.js 构建 |
| `.gitea/workflows/docker-image.yml` | `main``test` push / 手动触发 | 构建 Docker 镜像、推送到镜像仓库,并通过 SSH 部署 |
这样可以避免所有开发分支都发布镜像,也能让代码检查失败时不污染镜像仓库。
## 必需 Secrets
在 Gitea 仓库的 Actions Secrets 中配置以下变量:
| Secret | 示例 | 说明 |
| --- | --- | --- |
| `REGISTRY_HOST` | `gitea.banlv-ai.com` | `docker login` 使用的镜像仓库地址 |
| `REGISTRY_IMAGE` | `gitea.banlv-ai.com/admin/cozsweet-web` | 完整镜像仓库名,不包含 tag |
| `REGISTRY_USERNAME` | `cozsweet-bot` | 镜像仓库用户名 |
| `REGISTRY_PASSWORD` | `***` | 镜像仓库密码或访问令牌 |
| `GITEA_API_BASE_URL` | `https://gitea.banlv-ai.com/api/v1` | Gitea API 地址,用于清理旧镜像版本 |
| `GITEA_PACKAGE_TOKEN` | `***` | 具备 package 删除权限的 Gitea token |
| `TEST_ENV_FILE` | `.env.local` 的完整内容 | 测试环境构建期环境变量 |
| `PRODUCTION_ENV_FILE` | `.env.production` 的完整内容 | 生产环境构建期环境变量 |
Next.js 的 `NEXT_PUBLIC_*` 会在构建期固化到产物中,因此测试环境和生产环境会分别构建镜像。
## 镜像 Tag 规则
`test` 分支发布:
```bash
REGISTRY_IMAGE:test-<short_sha>
REGISTRY_IMAGE:test-latest
```
`main` 分支发布:
```bash
REGISTRY_IMAGE:prod-<short_sha>
REGISTRY_IMAGE:prod-latest
```
`<short_sha>` 用于精确回滚,`*-latest` 用于普通部署拉取最新版本。
## Runner 要求
当前 workflow 使用:
```yaml
runs-on: gitea-label
```
自托管 runner 需要满足:
1. 可以拉取并运行 job 容器镜像。
2. 当前 runner 用户可以访问 Docker daemon。
3. 能访问配置的镜像仓库。
4. 支持 Docker BuildKit secret,即 `DOCKER_BUILDKIT=1 docker build --secret ...`
当前 Docker 镜像发布 workflow 会使用 `cozsweet-act-runner-node24-docker:latest` 作为 job 容器,确保 `actions/checkout@v4` 执行时已经存在 Node.js,并且容器内已经包含 Docker CLI。runner 仍然需要挂载宿主机 Docker socket
```yaml
volumes:
- /var/run/docker.sock:/var/run/docker.sock
```
自定义 runner job 镜像的构建方式见 [Gitea Runner Job 镜像](./gitea-runner-image.md)。
## 验证方式
推送到 `test` 分支后,检查 Actions 日志中是否出现:
```text
Build Docker image
Push Docker image
```
服务器上可查看镜像:
```bash
docker pull REGISTRY_IMAGE:test-latest
docker image ls | grep cozsweet-web
```
如果使用 Gitea 自带 Container Registry,需要确认 Gitea 服务已开启 packages / container registry,并且 `REGISTRY_HOST` 与 Docker 登录地址一致。
## 部署服务器拉取镜像
当前推荐由 Gitea Actions 通过 SSH 登录部署服务器并执行部署脚本,不再依赖服务器 Git remote 的 `post-receive` hook。完整说明见 [Gitea Actions SSH 部署流程](./gitea-actions-ssh-deploy.md)。
如果需要在服务器上手动验证镜像拉取,可先登录镜像仓库:
```bash
docker login REGISTRY_HOST
```
Actions 部署时会根据当前分支和 commit 自动拉取:
```bash
gitea.banlv-ai.com/admin/cozsweet-web:test-<short_sha>
gitea.banlv-ai.com/admin/cozsweet-web:prod-<short_sha>
```
推荐优先使用默认的 `<env>-<short_sha>` 精确 tag,这样发布和回滚都更可控。
## 镜像保留策略
镜像推送成功后,workflow 会调用 Gitea Package API 清理远端 Container Registry
- `test-*` 精确 tag 只保留最近 3 个,`test-latest` 不计入也不删除。
- `prod-*` 精确 tag 只保留最近 3 个,`prod-latest` 不计入也不删除。
- 当前刚推送的 `IMAGE_VERSION_TAG` 永远不会被删除。
生产环境 SSH 部署成功后,服务器本机只保留当前正在运行的一个 `prod-*` 镜像;测试环境服务器本机暂不限制保留数量。