将所有 docker-compose(V1)替换为 docker compose(V2): - CI/CD 流水线、部署脚本、文档中的命令调用 - 安装包名 docker-compose → docker-compose-plugin
31 KiB
Duoqi API 部署与持续集成方案
基于 Gitea + 阿里云轻量应用服务器 (Alibaba Cloud Linux 3) 的私有化部署方案
目录
架构概览
为什么选择 Gitea 而不是 GitLab
| 对比项 | Gitea | GitLab CE |
|---|---|---|
| 最低内存 | ~200MB | ~4GB |
| 安装复杂度 | 单二进制文件 | 需要多组件 |
| CI/CD | Gitea Actions(兼容 GitHub Actions 语法) | GitLab CI/CD |
| 容器镜像仓库 | 内置(可选) | 内置 |
| 适合场景 | 小团队、资源有限 | 大团队、功能全面 |
| 2C/2G 可行性 | ✅ 完全可行 | ❌ 内存不足 |
单服务器资源分配(2C/2G)
┌─────────────────────────────────────────────────────────────────────┐
│ 阿里云轻量应用服务器 (2C/2G) │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Nginx 反向代理 (:80/:443 ← 唯一对外入口) │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌────────────────────────┐│ │
│ │ │ api.duoqi.me│ │test-api. │ │ git.duoqi.me ││ │
│ │ │ → :3000 prod │ │duoqi.me │ │ → :3200 Gitea (IP限制) ││ │
│ │ │ │ │ → :3001 test │ │ ││ │
│ │ └──────────────┘ └──────────────┘ └────────────────────────┘│ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │
│ │ duoqi-api │ │ duoqi-api │ │ Gitea + Act Runner │ │
│ │ (prod) │ │ (test) │ │ 代码托管 + CI/CD │ │
│ │ 127.0.0.1 │ │ 127.0.0.1 │ │ 127.0.0.1:3200 │ │
│ │ :3000 │ │ :3001 │ │ ~200MB │ │
│ │ ~300MB │ │ ~200MB │ └──────────────────────────┘ │
│ └─────────────┘ └──────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ 阿里云 RDS MySQL (外置,仅内网可达) │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ duoqi_prod │ │ duoqi_test │ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ └───────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
内存预算:
| 组件 | 预估占用 | 说明 |
|---|---|---|
| OS + 系统 | ~200MB | Alibaba Cloud Linux 3 |
| Docker | ~150MB | Docker Daemon |
| Gitea | ~200MB | 含 Act Runner |
| Nginx | ~50MB | 反向代理 |
| duoqi-api (prod) | ~300MB | 生产容器 |
| duoqi-api (test) | ~200MB | 测试容器(按需启停) |
| 合计 | ~1.1GB | 剩余 ~900MB 缓冲 |
Phase 1: 单服务器方案(当前)
资源规划
| 资源 | 配置 | 用途 |
|---|---|---|
| 轻量应用服务器 | 2C/2G/40GB SSD | Gitea + Docker + Nginx |
| 阿里云 RDS MySQL | 1C/1G 基础版 | duoqi_prod + duoqi_test |
| 域名 + SSL | api.duoqi.me | 生产环境入口 |
服务器初始化
系统选择 Alibaba Cloud Linux 3(阿里云官方优化内核,内存占用更低,与 RDS 兼容性更好)
# SSH 登录
ssh root@your-server-ip
# 1. 更新系统
dnf update -y
# 2. 安装基础工具
dnf install -y curl git nginx certbot python3-certbot-nginx
# 3. 安装 Docker(Alibaba Cloud Linux 内置 Docker 源)
dnf install -y docker docker-compose-plugin
systemctl enable --now docker
# 4. 配置防火墙(firewalld)
# 所有服务通过 Nginx 反向代理,只需开放 22/80/443
systemctl enable --now firewalld
firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
# 5. 创建项目目录
mkdir -p /opt/duoqi-api
mkdir -p /opt/gitea
mkdir -p /opt/backups
# 6. 验证
cat /etc/os-release # 确认 Alibaba Cloud Linux
docker --version
nginx -v
Gitea 安装与配置
方式一:二进制安装(推荐,更省内存)
Gitea 是单个 Go 二进制文件,直接运行在宿主机上比 Docker 方式省 ~50MB 内存,且 systemd 管理更可靠。 在 2C/2G 服务器上,省下的每一 MB 都有意义。
# 下载 Gitea
wget -O /usr/local/bin/gitea https://dl.gitea.io/gitea/1.22/gitea-1.22-linux-amd64
chmod +x /usr/local/bin/gitea
# 创建用户和目录
groupadd --system git
useradd --system --gid git --shell /bin/bash -m git
mkdir -p /var/lib/gitea/{custom,data,log}
chown -R git:git /var/lib/gitea
mkdir -p /etc/gitea
chown git:git /etc/gitea
# 创建 systemd 服务
cat > /etc/systemd/system/gitea.service << 'EOF'
[Unit]
Description=Gitea
After=network.target
[Service]
User=git
WorkingDirectory=/var/lib/gitea
ExecStart=/usr/local/bin/gitea web -c /etc/gitea/app.ini --port 3200 --http-addr 127.0.0.1
Restart=always
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea
[Install]
WantedBy=multi-user.target
EOF
# 启动
systemctl enable gitea
systemctl start gitea
# 等待 Gitea 生成默认配置文件
sleep 3
systemctl stop gitea
配置反向代理适配(关键步骤):
Gitea 需要知道自己对外是
https://git.duoqi.me,否则 Git clone URL 和 Web UI 链接会指向127.0.0.1:3200。
# 编辑 Gitea 配置文件
cat >> /etc/gitea/app.ini << 'EOF'
[server]
DOMAIN = git.duoqi.me
ROOT_URL = https://git.duoqi.me/
HTTP_ADDR = 127.0.0.1
HTTP_PORT = 3200
SSH_DOMAIN = git.duoqi.me
SSH_PORT = 22
SSH_LISTEN_PORT = 22
OFFLINE_MODE = true ; 禁用 Gravatar 等外部服务,加快页面加载
[security]
INSTALL_LOCK = true ; 已完成安装,禁止再次访问安装页面
[service]
REGISTER_EMAIL_CONFIRM = false ; 按需开启
DISABLE_REGISTRATION = true ; 禁止公开注册,仅管理员创建账号
[other]
SHOW_FOOTER_VERSION = false ; 隐藏版本号,减少信息泄露
EOF
# 修正权限
chown git:git /etc/gitea/app.ini
chmod 640 /etc/gitea/app.ini
# 启动
systemctl start gitea
方式二:Docker 部署(备选)
cat > /opt/gitea/docker-compose.yml << 'EOF'
version: '3.8'
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: unless-stopped
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__server__DOMAIN=git.duoqi.me
- GITEA__server__ROOT_URL=https://git.duoqi.me/
- GITEA__server__HTTP_ADDR=127.0.0.1
- GITEA__server__HTTP_PORT=3200
- GITEA__server__SSH_DOMAIN=git.duoqi.me
volumes:
- ./data:/data
- /etc/localtime:/etc/localtime:ro
network_mode: host ; 需要绑定 127.0.0.1,使用 host 网络
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
EOF
cd /opt/gitea && docker compose up -d
注意: Docker 方式会额外占用 ~50MB 内存(容器运行时开销),仅当需要快速试用或测试时使用。
Gitea 初始化配置
1. 浏览器访问 https://git.duoqi.me(通过 Nginx 反向代理)
首次启动时也可临时访问 http://127.0.0.1:3200
2. 首次配置(安装页面):
- 数据库:SQLite3(默认)
- 服务器域名:git.duoqi.me
- Gitea HTTP 监听端口:3200
- SSH 服务端口:22
- 管理员账号:创建 admin 用户
3. 创建仓库:duoqi-api
4. 推送代码(HTTP):
git remote add gitea https://git.duoqi.me/admin/duoqi-api.git
git push gitea main
git checkout -b develop
git push gitea develop
或使用 SSH:
git remote add gitea git@git.duoqi.me:admin/duoqi-api.git
git push gitea main
git checkout -b develop
git push gitea develop
安装 Act Runner(CI/CD 执行器)
# 下载 Act Runner
wget -O /usr/local/bin/act_runner https://gitea.com/gitea/act_runner/releases/latest/download/act_runner-linux-amd64
chmod +x /usr/local/bin/act_runner
# 在 Gitea Web UI 中生成 Token:
# Settings → Actions → Runners → Create new Runner → 复制 Token
# 创建专用工作目录(register 和 daemon 必须在同一目录)
mkdir -p /opt/act-runner
# 注册 Runner
cd /opt/act-runner && act_runner register \
--instance http://localhost:3200 \
--token YOUR_RUNNER_TOKEN \
--name duoqi-runner \
--labels ubuntu-latest:docker://oven/bun:latest
# 创建 systemd 服务
cat > /etc/systemd/system/act-runner.service << 'EOF'
[Unit]
Description=Gitea Act Runner
After=docker.service
[Service]
WorkingDirectory=/opt/act-runner
ExecStart=/usr/local/bin/act_runner daemon
Restart=always
Environment=HOME=/root
[Install]
WantedBy=multi-user.target
EOF
# 启动
systemctl daemon-reload
systemctl enable act-runner
systemctl start act-runner
# 验证:确认 active (running),且 Gitea Web UI 中 Runner 显示在线
systemctl status act-runner
环境隔离策略
RDS 数据库隔离
-- 连接到 RDS
mysql -h your-rds-endpoint -u root -p
-- 创建生产库
CREATE DATABASE duoqi_prod CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 创建测试库
CREATE DATABASE duoqi_test CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 创建用户并授权
CREATE USER 'duoqi_prod'@'%' IDENTIFIED BY 'prod-password';
GRANT ALL PRIVILEGES ON duoqi_prod.* TO 'duoqi_prod'@'%';
CREATE USER 'duoqi_test'@'%' IDENTIFIED BY 'test-password';
GRANT ALL PRIVILEGES ON duoqi_test.* TO 'duoqi_test'@'%';
FLUSH PRIVILEGES;
环境配置文件
密钥生成(在配置环境变量之前):
# 生成 JWT_SECRET(用于签名和验证用户 JWT)
openssl rand -base64 32
# 生成 ADMIN_TOKEN(管理后台认证令牌)
openssl rand -base64 32
# 或使用 Node.js 生成:
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
安全提示:
JWT_SECRET必须至少 32 字符(代码中有强制校验)- 生产环境和测试环境必须使用不同的密钥
- 密钥生成后应妥善保管,不要提交到 Git 仓库
- 可在任意服务器生成,关键是通过安全渠道传输到目标环境
生产环境 /opt/duoqi-api/.env.prod:
DATABASE_URL=mysql://duoqi_prod:prod-password@your-rds-endpoint:3306/duoqi_prod
JWT_SECRET=prod-super-secret-jwt-key # 替换为生成的密钥
JWT_EXPIRES_IN=1h
JWT_REFRESH_EXPIRES_IN=30d
ADMIN_TOKEN=prod-admin-token # 替换为生成的密钥
PORT=3000
NODE_ENV=production
LOG_LEVEL=warn
# ... 其他生产环境变量
测试环境 /opt/duoqi-api/.env.test:
DATABASE_URL=mysql://duoqi_test:test-password@your-rds-endpoint:3306/duoqi_test
JWT_SECRET=test-secret-key # 与生产环境不同
JWT_EXPIRES_IN=1h
JWT_REFRESH_EXPIRES_IN=30d
ADMIN_TOKEN=test-admin-token # 与生产环境不同
PORT=3001
NODE_ENV=test
LOG_LEVEL=debug
# ... 其他测试环境变量(可使用测试用的华为、OSS配置)
Docker Compose 环境隔离
服务器 compose 文件 /opt/duoqi-api/docker-compose.yml:
version: '3.8'
services:
# ===== 生产环境 =====
api-prod:
build:
context: /opt/gitea/data/git/repositories/admin/duoqi-api.git
dockerfile: Dockerfile
image: duoqi-api:prod
container_name: duoqi-api-prod
restart: unless-stopped
env_file: .env.prod
ports:
- "3000:3000"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
deploy:
resources:
limits:
memory: 400M
# ===== 测试环境(按需启停) =====
api-test:
build:
context: /opt/gitea/data/git/repositories/admin/duoqi-api.git
dockerfile: Dockerfile
image: duoqi-api:test
container_name: duoqi-api-test
restart: "no" # 不自动重启,手动控制
env_file: .env.test
ports:
- "3001:3001"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
logging:
driver: "json-file"
options:
max-size: "5m"
max-file: "2"
deploy:
resources:
limits:
memory: 300M
profiles:
- test # 使用 profiles 按需启停
启停命令:
# 只启动生产环境(默认)
docker compose up -d
# 启动生产 + 测试环境
docker compose --profile test up -d
# 停止测试环境(释放内存)
docker compose --profile test stop api-test
# 重新构建并启动
docker compose up -d --build api-prod
docker compose --profile test up -d --build api-test
CI/CD 流程
双分支工作流
develop 分支(开发测试) main 分支(生产发布)
│ │
▼ ▼
┌───────────┐ ┌───────────┐
│ quality │ ← Lint + 类型检查 │ quality │ ← Lint + 类型检查
└─────┬─────┘ └─────┬─────┘
▼ ▼
┌───────────┐ ┌───────────┐
│ test │ ← 单元测试 + 覆盖率 │ test │ ← 单元测试 + 覆盖率
└─────┬─────┘ └─────┬─────┘
▼ ▼
┌────────────┐ ┌────────────┐
│ build-test │ ← 构建测试镜像 │ build-prod │ ← 构建生产镜像
└─────┬──────┘ └─────┬──────┘
▼ ▼
┌─────────────┐ ┌─────────────┐
│ deploy-test │ ← 自动部署到测试 │ deploy-prod │ ← 手动确认后部署生产
└─────────────┘ └─────────────┘
日常开发流程
# 1. 在 develop 上开发
git checkout develop
# ... 编写代码 ...
git add .
git commit -m "feat: 新功能描述"
git push origin develop
# → 自动触发:quality → test → build-test → deploy-test
# 2. 在测试环境验证(http://test-api.duoqi.me)
# 如果发现问题,继续在 develop 上修改并 push
# 3. 测试通过,合并到 main 发布
git checkout main
git merge develop
git push origin main
# → 自动触发:quality → test → build-prod
# → 在 Gitea Web UI 手动确认 deploy-prod
触发规则
| 事件 | quality | test | build | deploy |
|---|---|---|---|---|
push 到 develop |
✅ | ✅ | build-test | deploy-test(自动) |
push 到 main |
✅ | ✅ | build-prod | deploy-prod(手动确认) |
注意:
develop分支需要在 Gitea 仓库中手动创建:git checkout -b develop git push origin develop
关键设计说明
| 设计决策 | 原因 |
|---|---|
| 双分支隔离(develop + main) | develop 是试验场,main 是稳定版本,互不干扰 |
| 不同分支构建不同镜像 | develop 只构建 test 镜像,main 只构建 prod 镜像,节省 2C/2G 服务器资源 |
| 本地构建镜像,无外部仓库 | 单服务器不需要镜像中转,节省资源 |
| 测试环境使用 Docker profiles | 按需启停,节省内存 |
| 生产部署手动确认 | 防止误操作,确保人工验证后才上线 |
| 使用 Gitea Actions | 兼容 GitHub Actions 语法,学习成本低 |
部署操作
手动部署(首次或紧急)
# SSH 登录服务器
ssh root@your-server-ip
cd /opt/duoqi-api
# 从 Gitea 拉取最新代码
git -C /opt/duoqi-api/repo pull # 如果用 git clone 方式
# 或使用部署脚本
bash scripts/deploy.sh prod
使用部署脚本
# 部署到生产环境
bash scripts/deploy.sh prod
# 部署到测试环境
bash scripts/deploy.sh test
# 停止测试环境
bash scripts/deploy.sh test-stop
# 查看状态
bash scripts/deploy.sh status
# 回滚
bash scripts/deploy.sh rollback prod
Nginx 配置
所有服务通过 Nginx 统一入口,后端端口仅绑定 localhost,防火墙只开 22/80/443。
# 生产环境 API
cat > /etc/nginx/conf.d/duoqi-api.conf << 'EOF'
server {
listen 80;
server_name api.duoqi.me;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
EOF
# 测试环境 API(仅限内部访问)
cat > /etc/nginx/conf.d/duoqi-api-test.conf << 'EOF'
server {
listen 80;
server_name test-api.duoqi.me;
# 限制访问 IP(开发团队办公网络)
# allow 123.56.78.90;
# deny all;
location / {
proxy_pass http://localhost:3001;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
EOF
# Gitea 代码仓库(限制访问 IP,仅团队可访问)
cat > /etc/nginx/conf.d/gitea.conf << 'EOF'
server {
listen 80;
server_name git.duoqi.me;
# 限制访问 IP(开发团队办公网络)
# allow 123.56.78.90;
# deny all;
location / {
proxy_pass http://127.0.0.1:3200;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Gitea 需要较大的请求体(git push)
client_max_body_size 100M;
}
}
EOF
# 验证并生效
nginx -t
systemctl enable --now nginx
systemctl reload nginx
配置 HTTPS
# 为三个域名统一申请证书
certbot --nginx -d api.duoqi.me -d test-api.duoqi.me -d git.duoqi.me
# 自动续期验证
certbot renew --dry-run
Note
在子域名还没有配置解析的前提下,会影响证书的签发。后期如果新增子域名,并且需要同一张证书时,可以通过
--expand参数进行申请。
# 方案1:先申请已就绪的子域名
sudo certbot --nginx -d example.com -d www.example.com
# 后续子域名就绪后,再扩容证书
sudo certbot --nginx --expand \
-d example.com -d www.example.com -d api.example.com -d blog.example.com
常见错误
# ❌ 错误:只写新增域名,会导致原有域名被移除!
sudo certbot --nginx --expand -d api.example.com -d blog.example.com
# ✅ 正确:列出所有域名(原有 + 新增)
sudo certbot --nginx --expand \
-d example.com -d www.example.com -d api.example.com -d blog.example.com
Phase 2: 多服务器扩展(未来)
架构演进
Phase 1 (当前) Phase 2 (扩展后)
┌──────────────┐ ┌─────────────────────────────────┐
│ 单台服务器 │ │ 负载均衡 (SLB/Nginx) │
│ │ │ api.duoqi.me → 443/80 │
│ Gitea │ └──────────┬──────────────────────┘
│ duoqi-api │ ──────▶ │
│ duoqi-api │ ┌──────────┴──────────┐
│ (prod+test) │ │ │
│ Nginx │ ┌────┴────┐ ┌─────┴────┐
└──────────────┘ │ API-1 │ │ API-2 │
│ (prod) │ │ (prod) │
┌──────────────┐ └─────────┘ └──────────┘
│ RDS MySQL │ ┌─────────────┐ ┌──────────────┐
│ duoqi_prod │ │ CI/CD 服务器 │ │ 测试服务器 │
│ duoqi_test │ │ Gitea │ │ duoqi-api │
└──────────────┘ │ Harbor 镜像 │ │ (test) │
└─────────────┘ └──────────────┘
扩展触发条件
当出现以下情况时,考虑从 Phase 1 升级到 Phase 2:
| 指标 | Phase 1 上限 | Phase 2 起步 |
|---|---|---|
| 日活用户 | ~1,000 | >1,000 |
| 内存使用率 | 持续 >80% | — |
| CPU 使用率 | 持续 >70% | — |
| 需要独立测试服务器 | 否 | 是 |
| 需要多实例高可用 | 否 | 是 |
私有镜像仓库
多服务器场景下需要镜像仓库统一分发:
方案一:Gitea 内置 Container Registry(推荐)
# 在 Gitea 的 app.ini 中启用
[packages]
ENABLED = true
STORAGE_TYPE = local
# 推送镜像
docker build -t your-server-ip:3200/admin/duoqi-api:latest .
docker push your-server-ip:3200/admin/duoqi-api:latest
方案二:Harbor(大规模场景)
# docker-compose.harbor.yml
# 需要独立服务器或至少 4GB 内存
services:
harbor:
image: goharbor/harbor:latest
# ... Harbor 企业级镜像仓库
负载均衡与水平扩展
# Phase 2: 多实例 docker-compose.yml
# API 服务器上的配置
version: '3.8'
services:
api:
image: your-registry/duoqi-api:latest
deploy:
replicas: 2 # 运行 2 个实例
resources:
limits:
cpus: '1'
memory: 512M
env_file: .env.prod
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 15s
timeout: 5s
retries: 3
阿里云 SLB 配置:
1. 创建负载均衡实例
2. 添加后端服务器(API-1, API-2)
3. 配置健康检查路径:/health
4. 配置 SSL 证书
5. 域名 DNS 解析到 SLB 公网 IP
Phase 2 CI/CD 流程
推送代码 → Gitea Actions → 构建 + 推送到私有镜像仓库
│
┌───────────────┼───────────────┐
▼ ▼ ▼
部署到测试服务器 部署到 API-1 部署到 API-2
(自动) (手动/灰度) (手动/灰度)
运维管理
日常维护命令
# 查看所有容器状态
docker compose ps
# 查看生产日志
docker compose logs -f api-prod
# 查看测试日志
docker compose --profile test logs -f api-test
# 重启生产环境
docker compose restart api-prod
# 进入容器调试
docker compose exec api-prod sh
# 查看资源使用
docker stats --no-stream
数据库管理
# 测试库重置(清空测试数据)
mysql -h your-rds-endpoint -u duoqi_test -p -e "DROP DATABASE duoqi_test; CREATE DATABASE duoqi_test CHARACTER SET utf8mb4;"
# 执行迁移
docker compose exec api-prod npx drizzle-kit migrate
# 导入种子数据到测试库
docker compose --profile test exec api-test bun run db:seed
# 备份生产库
mysqldump -h your-rds-endpoint -u duoqi_prod -p duoqi_prod > /opt/backups/duoqi_prod_$(date +%Y%m%d).sql
备份策略
# 创建备份脚本
cat > /opt/backups/backup.sh << 'SCRIPT'
#!/bin/bash
set -e
BACKUP_DIR="/opt/backups"
DATE=$(date +%Y%m%d_%H%M%S)
# 数据库备份
mysqldump -h your-rds-endpoint -u duoqi_prod -pyour-password duoqi_prod \
| gzip > "$BACKUP_DIR/db_prod_$DATE.sql.gz"
# Gitea 仓库备份
sudo -u git gitea dump -c /etc/gitea/app.ini
# 备份文件生成在当前目录:gitea-dump-*.zip
# 保留最近 7 天的备份
find $BACKUP_DIR -name "*.gz" -mtime +7 -delete
echo "[$DATE] Backup completed"
SCRIPT
chmod +x /opt/backups/backup.sh
# 定时任务(每天凌晨 2 点)
echo "0 2 * * * /opt/backups/backup.sh >> /opt/backups/backup.log 2>&1" | crontab -
故障排查
常见问题
1. 内存不足
# 查看内存使用
free -h
# 停止测试环境释放内存
docker compose --profile test stop api-test
# 清理 Docker 缓存
docker system prune -f
# 查看 Docker 磁盘占用
docker system df
2. 容器启动失败
# 查看退出日志
docker compose logs api-prod
# 检查环境变量
docker compose config
# 检查端口冲突
netstat -tlnp | grep -E '3000|3001'
3. Gitea Runner 不可用
# 检查 Runner 状态
systemctl status act-runner
# 重启 Runner
systemctl restart act-runner
# 查看日志
journalctl -u act-runner -f
4. 数据库连接失败
# 从服务器测试 RDS 连通性
mysql -h your-rds-endpoint -u duoqi_prod -p -e "SELECT 1;"
# 检查 RDS 白名单是否包含服务器 IP
# 阿里云 RDS 控制台 → 数据安全性 → 白名单设置
回滚操作
# 查看本地镜像历史
docker images | grep duoqi-api
# 回滚到上一个版本
cd /opt/duoqi-api
docker compose down api-prod
# 修改 docker-compose.yml 使用指定版本镜像
docker compose up -d api-prod
附录
A. 完整目录结构(服务器端)
/opt/
├── gitea/ # Gitea 代码托管
│ ├── docker-compose.yml
│ └── data/ # Gitea 数据(仓库、配置)
├── duoqi-api/ # 应用部署
│ ├── docker-compose.yml # 包含 prod + test 配置
│ ├── .env.prod # 生产环境变量
│ ├── .env.test # 测试环境变量
│ ├── Dockerfile # 镜像构建
│ └── repo/ # Git 仓库(用于构建)
├── backups/ # 备份目录
│ ├── backup.sh
│ └── *.sql.gz
└── scripts/ # 运维脚本
└── deploy.sh
B. Gitea Actions 与 GitHub Actions 语法对照
| 特性 | GitHub Actions | Gitea Actions |
|---|---|---|
| 文件路径 | .github/workflows/ |
.gitea/workflows/ |
| 语法 | YAML | 相同(完全兼容) |
| 触发条件 | on: push |
相同 |
| Runner | GitHub 托管 | 自托管 Act Runner |
| 镜像 | runs-on: ubuntu-latest |
相同,或自定义标签 |
C. 安全建议
| 项目 | 建议 |
|---|---|
| SSH | 禁用密码登录,仅密钥认证 |
| 防火墙 | firewalld 仅开放 22/80/443,后端端口全部绑定 localhost |
| 测试环境 | 通过 Nginx 限制访问 IP |
| 数据库 | 生产用户和测试用户严格分离权限 |
| JWT | 生产与测试使用不同密钥 |
| SSL | 生产环境必须启用 HTTPS |
| 内核更新 | Alibaba Cloud Linux 安全补丁自动推送,及时更新 |
D. Ubuntu 与 Alibaba Cloud Linux 命令速查
| 操作 | Ubuntu (apt) | Alibaba Cloud Linux (dnf) |
|---|---|---|
| 更新系统 | apt update && apt upgrade -y |
dnf update -y |
| 安装软件 | apt install -y <pkg> |
dnf install -y <pkg> |
| 安装 Docker | curl -fsSL https://get.docker.com | sh |
dnf install -y docker |
| 防火墙 | ufw allow 80/tcp |
firewall-cmd --permanent --add-port=80/tcp && firewall-cmd --reload |
| 创建用户 | adduser --system --group git |
groupadd --system git && useradd --system --gid git git |
| Nginx 配置 | /etc/nginx/sites-available/ |
/etc/nginx/conf.d/ |
文档版本: v5.0.0 (双分支工作流) 最后更新: 2026-04-16 维护者: Duoqi Team