feat: 添加 Docker Hub 自动构建和改进部署体验

- 支持环境变量预设管理员账号密码
- 添加 docker-entrypoint.sh 自动初始化脚本
- 配置 GitHub Actions 自动构建多平台镜像(amd64, arm64)
- 添加版本标签管理和自动发布流程
- 集成 Trivy 安全漏洞扫描
- 更新文档说明 Docker Hub 使用方法
- 优化 Docker 部署用户体验

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
shaw
2025-07-19 00:49:04 +08:00
parent f5968e518e
commit 5c83cf1d53
12 changed files with 691 additions and 6 deletions

109
.github/DOCKER_HUB_SETUP.md vendored Normal file
View File

@@ -0,0 +1,109 @@
# Docker Hub 自动发布配置指南
本文档说明如何配置 GitHub Actions 自动构建并发布 Docker 镜像到 Docker Hub。
## 📋 前置要求
1. Docker Hub 账号
2. GitHub 仓库的管理员权限
## 🔐 配置 GitHub Secrets
在 GitHub 仓库中配置以下 secrets
1. 进入仓库设置:`Settings``Secrets and variables``Actions`
2. 点击 `New repository secret`
3. 添加以下 secrets
### 必需的 Secrets
| Secret 名称 | 说明 | 如何获取 |
|------------|------|---------|
| `DOCKERHUB_USERNAME` | Docker Hub 用户名 | 你的 Docker Hub 登录用户名 |
| `DOCKERHUB_TOKEN` | Docker Hub Access Token | 见下方说明 |
### 获取 Docker Hub Access Token
1. 登录 [Docker Hub](https://hub.docker.com/)
2. 点击右上角头像 → `Account Settings`
3. 选择 `Security``Access Tokens`
4. 点击 `New Access Token`
5. 填写描述(如:`GitHub Actions`
6. 选择权限:`Read, Write, Delete`
7. 点击 `Generate`
8. **立即复制 token**(只显示一次)
## 🚀 工作流程说明
### 触发条件
- **自动触发**:推送到 `main` 分支
- **版本发布**:创建 `v*` 格式的 tag`v1.0.0`
- **手动触发**:在 Actions 页面手动运行
### 镜像标签策略
工作流会自动创建以下标签:
- `latest`:始终指向 main 分支的最新构建
- `main`main 分支的构建
- `v1.0.0`:版本标签(当创建 tag 时)
- `1.0`:主次版本标签
- `1`:主版本标签
- `main-sha-xxxxxxx`:包含 commit SHA 的标签
### 支持的平台
- `linux/amd64`Intel/AMD 架构
- `linux/arm64`ARM64 架构(如 Apple Silicon, 树莓派等)
## 📦 使用发布的镜像
```bash
# 拉取最新版本
docker pull weishaw/claude-relay-service:latest
# 拉取特定版本
docker pull weishaw/claude-relay-service:v1.0.0
# 运行容器
docker run -d \
--name claude-relay \
-p 3000:3000 \
-v ./data:/app/data \
-v ./logs:/app/logs \
-e ADMIN_USERNAME=my_admin \
-e ADMIN_PASSWORD=my_password \
weishaw/claude-relay-service:latest
```
## 🔍 验证配置
1. 推送代码到 main 分支
2. 在 GitHub 仓库页面点击 `Actions` 标签
3. 查看 `Docker Build & Push` 工作流运行状态
4. 成功后在 Docker Hub 查看镜像
## 🛡️ 安全功能
- **漏洞扫描**:使用 Trivy 自动扫描镜像漏洞
- **扫描报告**:上传到 GitHub Security 标签页
- **自动更新 README**:同步更新 Docker Hub 的项目描述
## ❓ 常见问题
### 构建失败
- 检查 secrets 是否正确配置
- 确认 Docker Hub token 有足够权限
- 查看 Actions 日志详细错误信息
### 镜像推送失败
- 确认 Docker Hub 用户名正确
- 检查是否达到 Docker Hub 免费账户限制
- Token 可能过期,需要重新生成
### 多平台构建慢
这是正常的,因为需要模拟不同架构。可以在不需要时修改 `platforms` 配置。

114
.github/WORKFLOW_USAGE.md vendored Normal file
View File

@@ -0,0 +1,114 @@
# GitHub Actions 工作流使用指南
## 📋 概述
本项目配置了自动化 CI/CD 流程,每次推送到 main 分支都会自动构建并发布 Docker 镜像到 Docker Hub。
## 🚀 工作流程
### 1. Docker 构建和发布 (`docker-publish.yml`)
**功能:**
- 自动构建多平台 Docker 镜像amd64, arm64
- 推送到 Docker Hub
- 执行安全漏洞扫描
- 更新 Docker Hub 描述
**触发条件:**
- 推送到 `main` 分支
- 创建版本标签(如 `v1.0.0`
- Pull Request仅构建不推送
- 手动触发
### 2. 发布管理 (`release.yml`)
**功能:**
- 自动创建 GitHub Release
- 生成更新日志
- 关联 Docker 镜像版本
**触发条件:**
- 创建版本标签(如 `v1.0.0`
## 📝 版本发布流程
### 1. 常规更新(推送到 main
```bash
git add .
git commit -m "fix: 修复登录问题"
git push origin main
```
**结果:**
- 自动构建并推送 `latest` 标签到 Docker Hub
- 更新 `main` 标签
### 2. 版本发布
```bash
# 创建版本标签
git tag -a v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0
```
**结果:**
- 构建并推送以下标签到 Docker Hub
- `v1.0.0`(完整版本)
- `1.0`(主次版本)
- `1`(主版本)
- `latest`(最新版本)
- 创建 GitHub Release
- 生成更新日志
## 🔧 手动触发构建
1. 访问仓库的 Actions 页面
2. 选择 "Docker Build & Push" 工作流
3. 点击 "Run workflow"
4. 选择分支并运行
## 📊 查看构建状态
- **Actions 页面**:查看所有工作流运行历史
- **README 徽章**:实时显示构建状态
- **Docker Hub**:查看镜像标签和拉取次数
## 🛡️ 安全扫描
每次构建都会运行 Trivy 安全扫描:
- 扫描结果上传到 GitHub Security 标签页
- 发现高危漏洞会在 Actions 日志中警告
## ❓ 常见问题
### Q: 如何回滚到之前的版本?
```bash
# 使用特定版本标签
docker pull weishaw/claude-relay-service:v1.0.0
# 或在 docker-compose.yml 中指定版本
image: weishaw/claude-relay-service:v1.0.0
```
### Q: 如何跳过自动构建?
在 commit 消息中添加 `[skip ci]`
```bash
git commit -m "docs: 更新文档 [skip ci]"
```
### Q: 构建失败如何调试?
1. 查看 Actions 日志详细错误信息
2. 在本地测试 Docker 构建:
```bash
docker build -t test .
```
## 📚 相关文档
- [Docker Hub 配置指南](.github/DOCKER_HUB_SETUP.md)
- [GitHub Actions 文档](https://docs.github.com/en/actions)
- [Docker 官方文档](https://docs.docker.com/)

68
.github/cliff.toml vendored Normal file
View File

@@ -0,0 +1,68 @@
# git-cliff configuration file
# https://git-cliff.org/docs/configuration
[changelog]
# changelog header
header = """
# Changelog
All notable changes to this project will be documented in this file.
"""
# template for the changelog body
body = """
{% if version %}\
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
## [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits %}
- {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}](https://github.com/orhun/git-cliff/commit/{{ commit.id }}))
{%- endfor %}
{% endfor %}\n
"""
# remove the leading and trailing whitespace from the template
trim = true
# changelog footer
footer = """
"""
[git]
# parse the commits based on https://www.conventionalcommits.org
conventional_commits = true
# filter out the commits that are not conventional
filter_unconventional = true
# process each line of a commit as an individual commit
split_commits = false
# regex for preprocessing the commit messages
commit_preprocessors = [
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/orhun/git-cliff/issues/${2}))" },
]
# regex for parsing and grouping commits
commit_parsers = [
{ message = "^feat", group = "Features" },
{ message = "^fix", group = "Bug Fixes" },
{ message = "^docs", group = "Documentation" },
{ message = "^perf", group = "Performance" },
{ message = "^refactor", group = "Refactor" },
{ message = "^style", group = "Styling" },
{ message = "^test", group = "Testing" },
{ message = "^chore\\(release\\): prepare for", skip = true },
{ message = "^chore", group = "Miscellaneous Tasks" },
{ body = ".*security", group = "Security" },
]
# protect breaking changes from being skipped due to matching a skipping commit_parser
protect_breaking_commits = false
# filter out the commits that are not matched by commit parsers
filter_commits = false
# glob pattern for matching git tags
tag_pattern = "v[0-9]*"
# regex for skipping tags
skip_tags = "v0.1.0-beta.1"
# regex for ignoring tags
ignore_tags = ""
# sort the tags topologically
topo_order = false
# sort the commits inside sections by oldest/newest order
sort_commits = "oldest"

101
.github/workflows/docker-publish.yml vendored Normal file
View File

@@ -0,0 +1,101 @@
name: Docker Build & Push
on:
push:
branches: [ main ]
tags:
- 'v*'
pull_request:
branches: [ main ]
workflow_dispatch:
env:
REGISTRY: docker.io
IMAGE_NAME: ${{ secrets.DOCKERHUB_USERNAME }}/claude-relay-service
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
test:
needs: build
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
steps:
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.IMAGE_NAME }}:latest
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: 'trivy-results.sarif'
update-description:
needs: build
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Update Docker Hub Description
uses: peter-evans/dockerhub-description@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
repository: ${{ secrets.DOCKERHUB_USERNAME }}/claude-relay-service
readme-filepath: ./README.md
short-description: "Claude Code API Relay Service - 多账户管理的Claude API中转服务"

48
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,48 @@
name: Create Release
on:
push:
tags:
- 'v*'
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate changelog
id: changelog
uses: orhun/git-cliff-action@v3
with:
config: .github/cliff.toml
args: --latest --strip header
- name: Create Release
uses: softprops/action-gh-release@v1
with:
body: |
## 🐳 Docker 镜像
```bash
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/claude-relay-service:${{ github.ref_name }}
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/claude-relay-service:latest
```
## 📦 主要更新
${{ steps.changelog.outputs.content }}
## 📋 完整更新日志
查看 [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md)
draft: false
prerelease: false
generate_release_notes: true