Docker 部署 Sub2API:搭建多模型订阅 API 网关
Claude、OpenAI、Gemini、Grok 等服务各有认证方式和调用协议。Sub2API 把这些账号接入、请求转发、配额与用户管理集中到一个后台,对外提供统一的 API 网关。
这套部署固定使用 2026 年 8 月 25 日发布的 0.1.183 镜像,运行 Sub2API、PostgreSQL 18 和 Redis 8 三个容器。数据保存在部署目录中,适合单台 Linux 服务器长期自托管,也方便整目录迁移。
Sub2API 会处理上游账号、OAuth 凭据和 API Key。部署者需要遵守对应服务商的账号、订阅和共享规则,不要把管理后台或原始凭据暴露给不受信任的用户。
部署结论
| 项目 | 本文采用的值 |
|---|---|
| GitHub 地址 | Wei-Shaw/sub2api |
| 官方镜像 | weishaw/sub2api:0.1.183 |
| Sub2API 版本 | 0.1.183,对应 Git 标签 v0.1.183 |
| 部署方式 | Docker Compose,本地目录持久化版 |
| 适用范围 | 单机、自托管、长期运行 |
| 主机架构 | linux/amd64、linux/arm64 |
| 最低资源 | 官方没有给出统一最低配置;容量取决于并发量、数据库和日志规模 |
| 对外端口 | 宿主机 8080 → Sub2API 容器 8080 |
| 持久化目录 | ./data、./postgres_data、./redis_data |
| 依赖服务 | PostgreSQL 18-alpine、Redis 8-alpine |
| 验证范围 | 官方配置与发布记录核对;Compose 静态解析 |
| 资料核对日期 | 2026-08-26 |
官方同时提供命名卷版 docker-compose.yml,但部署文档明确推荐 docker-compose.local.yml:三个数据目录都能直接看到,备份、搬迁和故障恢复更直观。本文只展开这条路径。
三个容器怎么配合
正在准备渲染...
查看源码
flowchart LR
client["API 客户端 / 管理员浏览器"] -->|"HTTP 8080;公网建议 HTTPS"| app["Sub2API 0.1.183"]
app -->|"内部网络 5432"| pg[("PostgreSQL 18")]
app -->|"内部网络 6379"| redis[("Redis 8")]
app --> appdata["./data"]
pg --> pgdata["./postgres_data"]
redis --> redisdata["./redis_data"]只有 Sub2API 的 8080 端口映射到宿主机。PostgreSQL 和 Redis 不对外开放端口,应用通过 Compose 创建的 sub2api-network 访问它们。Sub2API 会等待数据库和缓存通过健康检查后再启动,并通过 /health 检查自身状态。
部署前检查
官方中文说明要求 Docker 20.10+ 和 Docker Compose v2。服务器还需要 curl 与 openssl:前者下载版本固定的部署文件,后者生成不会出现在文章里的随机密钥。
docker --version
docker compose version
curl --version
openssl version确认宿主机的 8080 端口没有被占用:
ss -lntp | grep ':8080 ' || true如果这里已有监听进程,可以在后面的 .env 中修改 SERVER_PORT。容器内部端口仍然保持 8080。
下载版本固定的部署文件
部署目录使用 /opt/sub2api。下面的 URL 指向 v0.1.183 标签,不会随 main 分支更新而改变。
sudo mkdir -p /opt/sub2api
sudo chown "$(id -u):$(id -g)" /opt/sub2api
cd /opt/sub2api
curl -fL --retry 3 \
-o compose.yaml \
https://raw.githubusercontent.com/Wei-Shaw/sub2api/v0.1.183/deploy/docker-compose.local.yml
curl -fL --retry 3 \
-o .env.example \
https://raw.githubusercontent.com/Wei-Shaw/sub2api/v0.1.183/deploy/.env.example官方 Compose 文件默认跟随浮动标签。把它替换为本文核对过的版本,再检查三个镜像引用:
sed -i 's#weishaw/sub2api:latest#weishaw/sub2api:0.1.183#' compose.yaml
grep -n 'image:' compose.yaml输出应包含:
weishaw/sub2api:0.1.183
postgres:18-alpine
redis:8-alpine仓库里的 deploy/DOCKER.md 还保留了一份简化示例,其中数据库和缓存版本较旧。本文以 v0.1.183 标签下可执行的 docker-compose.local.yml 为准,没有混用那份旧示例。
生成环境变量和密钥
Compose 真正强制要求的是 POSTGRES_PASSWORD。JWT_SECRET 为空时,每次启动会生成新值,现有登录会话随之失效;TOTP_ENCRYPTION_KEY 为空则会让已经绑定的双因素认证失效。因此这三个值都应该在第一次启动前固定下来。
下面还为 Redis 和管理员账号生成独立密码。所有随机值只写入当前目录的 .env,不会打印到终端。
cd /opt/sub2api
umask 077
POSTGRES_PASSWORD="$(openssl rand -hex 32)"
REDIS_PASSWORD="$(openssl rand -hex 32)"
JWT_SECRET="$(openssl rand -hex 32)"
TOTP_ENCRYPTION_KEY="$(openssl rand -hex 32)"
ADMIN_PASSWORD="$(openssl rand -hex 24)"
cat > .env <<EOF
BIND_HOST=0.0.0.0
SERVER_PORT=8080
SERVER_MODE=release
RUN_MODE=standard
TZ=Asia/Shanghai
POSTGRES_USER=sub2api
POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
POSTGRES_DB=sub2api
REDIS_PASSWORD=${REDIS_PASSWORD}
REDIS_DB=0
ADMIN_EMAIL=admin@sub2api.local
ADMIN_PASSWORD=${ADMIN_PASSWORD}
JWT_SECRET=${JWT_SECRET}
JWT_EXPIRE_HOUR=24
TOTP_ENCRYPTION_KEY=${TOTP_ENCRYPTION_KEY}
EOF
chmod 600 .env
unset POSTGRES_PASSWORD REDIS_PASSWORD JWT_SECRET TOTP_ENCRYPTION_KEY ADMIN_PASSWORDADMIN_EMAIL 可以换成自己的管理邮箱。公网部署不建议长期使用 admin@sub2api.local,但不要把真实账号和密钥写进准备公开的教程、截图或代码仓库。
查看管理员密码时只在服务器本机执行:
grep '^ADMIN_PASSWORD=' /opt/sub2api/.env创建数据目录并检查 Compose
cd /opt/sub2api
mkdir -p data postgres_data redis_data backups
docker compose --env-file .env -f compose.yaml config --quiet
docker compose --env-file .env -f compose.yaml config --images第一条命令没有输出并返回状态码 0,说明环境变量和 Compose 语法能够正确展开。第二条命令应列出固定版本的 Sub2API、PostgreSQL 18 和 Redis 8。
不要在配置检查前启动容器。POSTGRES_PASSWORD 缺失时,官方 Compose 会直接报错并终止;这是为了避免数据库以错误凭据初始化。
启动 Sub2API
cd /opt/sub2api
docker compose --env-file .env -f compose.yaml pull
docker compose --env-file .env -f compose.yaml up -d
docker compose --env-file .env -f compose.yaml psPostgreSQL 和 Redis 会先启动。两者健康后,Sub2API 执行自动初始化:连接依赖服务、应用数据库迁移、创建管理员账号,并在 ./data 中生成配置。
用有界日志查看最近的初始化结果,避免把持续跟随日志的命令留在无人值守终端里:
docker compose --env-file .env -f compose.yaml logs --tail=150 sub2api验证部署结果
容器和健康状态
cd /opt/sub2api
docker compose --env-file .env -f compose.yaml ps
curl -fsS http://127.0.0.1:8080/health && echo三个容器都应处于运行状态,Sub2API 最终应显示为 healthy。健康接口返回成功状态后,才继续配置上游账号。
PostgreSQL 与 Redis
docker compose --env-file .env -f compose.yaml exec -T postgres \
pg_isready -U sub2api -d sub2api
docker compose --env-file .env -f compose.yaml exec -T redis \
redis-cli ping数据库应报告 accepting connections,Redis 应返回 PONG。Redis 容器通过 REDISCLI_AUTH 读取 .env 中的密码,不需要把密码放进命令行。
数据库迁移记录
docker compose --env-file .env -f compose.yaml exec -T postgres \
psql -U sub2api -d sub2api -c \
'SELECT filename, applied_at FROM schema_migrations ORDER BY filename DESC LIMIT 5;'官方部署说明指出,迁移文件按文件名顺序执行,并将文件名与校验和记录到 schema_migrations。能查到记录,说明初始化不只是容器启动成功,数据库结构也已经落地。
宿主机持久化目录
du -sh data postgres_data redis_data
find data -maxdepth 2 -type f -print | head -20docker compose restart sub2api 不会删除这些目录。不要用删除容器或重启成功来代替备份恢复测试;持久化只说明数据路径存在。
首次登录和最小配置
在服务器本机打开 http://127.0.0.1:8080。从其他电脑访问时,使用 http://服务器实际IP:8080,同时把防火墙来源限制在可信 IP;公网长期运行应先完成后面的 HTTPS 和源站隔离。
使用 .env 中的 ADMIN_EMAIL 和 ADMIN_PASSWORD 登录。Docker Compose 设置了 AUTO_SETUP=true,这条部署路径不需要再走 Web Setup Wizard。
登录后按实际用途添加 Claude、OpenAI、Gemini 或其他上游账号。OAuth Client Secret、刷新令牌和 API Key 都属于高敏感数据:不要放进公共仓库,也不要出现在管理后台截图中。
日常管理
cd /opt/sub2api
# 查看状态
docker compose --env-file .env -f compose.yaml ps
# 查看最近 100 行应用日志
docker compose --env-file .env -f compose.yaml logs --tail=100 sub2api
# 只重启应用,不中断数据库和 Redis
docker compose --env-file .env -f compose.yaml restart sub2api
# 停止整套服务,保留数据目录
docker compose --env-file .env -f compose.yaml stop
# 重新启动
docker compose --env-file .env -f compose.yaml start应用日志还会写入 ./data/logs/。官方 .env.example 默认启用滚动:单文件 100 MB、保留 10 个历史文件、历史日志保留 7 天并压缩。磁盘较小时应同步调整这些参数并监控目录占用。
备份与恢复
整目录压缩适合搬迁,但数据库正在写入时直接打包 postgres_data 不能替代 PostgreSQL 原生备份。下面先停止应用写入,再分别备份数据库、Redis 和应用文件。
cd /opt/sub2api
STAMP="$(date +%Y%m%d-%H%M%S)"
docker compose --env-file .env -f compose.yaml stop sub2api
docker compose --env-file .env -f compose.yaml exec -T postgres \
pg_dump -U sub2api -d sub2api -Fc \
> "backups/postgres-${STAMP}.dump"
docker compose --env-file .env -f compose.yaml exec -T redis \
redis-cli SAVE
tar --exclude='./backups' -czf "backups/state-${STAMP}.tar.gz" \
compose.yaml .env data redis_data
docker compose --env-file .env -f compose.yaml start sub2api
sha256sum "backups/postgres-${STAMP}.dump" \
"backups/state-${STAMP}.tar.gz" \
> "backups/checksums-${STAMP}.txt".env 包含数据库、Redis、JWT、TOTP 和管理员密钥。备份文件应加密后再复制到另一台机器或对象存储,访问权限不能比生产服务器更宽。
恢复演练应放在另一台测试主机。官方 Compose 使用了固定容器名,同一台 Docker 主机上直接启动第二套配置会与生产容器冲突。先把状态归档和数据库备份复制到测试主机,核对校验和,再执行:
read -r -p "状态归档的绝对路径: " STATE_ARCHIVE
read -r -p "PostgreSQL 备份的绝对路径: " POSTGRES_DUMP
test -f "$STATE_ARCHIVE" && test -f "$POSTGRES_DUMP"
sudo mkdir -p /opt/sub2api-restore
sudo chown "$(id -u):$(id -g)" /opt/sub2api-restore
cd /opt/sub2api-restore
tar -xzf "$STATE_ARCHIVE"
mkdir -p postgres_data backups
cp "$POSTGRES_DUMP" backups/restore.dump
docker compose --env-file .env -f compose.yaml up -d postgres redis
docker compose --env-file .env -f compose.yaml ps等 PostgreSQL 和 Redis 都显示为 healthy 后,把逻辑备份恢复到测试数据库:
cd /opt/sub2api-restore
docker compose --env-file .env -f compose.yaml exec -T postgres \
pg_restore -U sub2api -d sub2api \
--clean --if-exists --no-owner --no-privileges \
< backups/restore.dump
docker compose --env-file .env -f compose.yaml up -d sub2api
docker compose --env-file .env -f compose.yaml ps
curl -fsS http://127.0.0.1:8080/health && echo最后检查迁移记录、管理员登录、账号配置和一条低成本 API 请求。数据库恢复会改写目标库;生产库不要用作第一次恢复演练,也不要在验证完成前切换流量。
升级与回滚
Sub2API 的数据库迁移是 forward-only。升级后如果新版本写入了不可逆结构,单纯把镜像标签改回旧版并不构成完整回滚。
升级前先执行上一节的备份,然后设置目标版本:
cd /opt/sub2api
cp compose.yaml compose.yaml.pre-upgrade
read -r -p "目标版本(不含 v): " TARGET_VERSION
test -n "$TARGET_VERSION"
docker manifest inspect "weishaw/sub2api:${TARGET_VERSION}" > /dev/null
sed -i -E \
"s#weishaw/sub2api:[^[:space:]]+#weishaw/sub2api:${TARGET_VERSION}#" \
compose.yaml
docker compose --env-file .env -f compose.yaml config --quiet
docker compose --env-file .env -f compose.yaml pull sub2api
docker compose --env-file .env -f compose.yaml up -d sub2api
docker compose --env-file .env -f compose.yaml logs --tail=150 sub2api输入已经发布并完成资料核对的实际版本,随后阅读对应 Release Notes。验收失败时,停止新应用,恢复升级前 PostgreSQL 备份和状态文件,再使用 compose.yaml.pre-upgrade 启动旧镜像。没有数据库备份时,不要把回退镜像描述成安全回滚。
公网部署需要补上的防护
直接把 8080 暴露到公网只适合短期验证。长期运行至少处理下面几项:
- 把
.env的BIND_HOST改为127.0.0.1,重新创建 Sub2API 容器,让源站只接受本机反向代理连接。 - 使用 Nginx、Caddy 或 CDN 提供 HTTPS,并把防火墙入口限制到
80/443或可信代理地址。 - Sub2API 存在长时间 SSE 与 WebSocket 请求。反向代理需要关闭响应缓冲,保留 Upgrade 头,并把读写超时设置到能覆盖长生成任务的范围。
- 不要压缩
text/event-stream。压缩和缓冲都可能让流式输出积压到请求结束才返回。 - 只有反向代理确实覆盖并清洗转发头时,才信任
X-Forwarded-For、X-Real-IP或 CDN 客户端 IP 头;同时阻止用户绕过代理直连源站。 - 固定镜像版本,定期验证 PostgreSQL 备份可恢复,并对
data/logs、数据库和宿主机磁盘设置监控。
项目提供了专门的 Edge and HTTP Ingress Security 文档,里面给出了适配 SSE、WebSocket、256 MiB 请求体和可信代理链的 Nginx/Caddy 基线。不要用普通静态网站的短超时代理配置直接替代。
镜像拉取受限时怎么处理
本文保留官方 Docker Hub 镜像。0.1.183 Release 同时公布了官方 GHCR 地址,Docker Hub 拉取失败时可以把 Compose 中的应用镜像替换为:
ghcr.io/wei-shaw/sub2api:0.1.183sed -i \
's#weishaw/sub2api:0.1.183#ghcr.io/wei-shaw/sub2api:0.1.183#' \
compose.yaml
docker compose --env-file .env -f compose.yaml pull sub2api这只是官方仓库之间的切换,不保证所有中国大陆网络都能稳定访问。本文没有把未经本次核验的公共镜像代理写成推荐地址。完全离线时,可以在联网机器拉取这三个固定版本镜像,用 docker save 导出,传输后校验文件 SHA-256,再在服务器执行 docker load。
常见问题
Sub2API 容器反复重启并提示 exec format error
项目 Issue #2061 记录过 docker-entrypoint.sh: exec format error。该 issue 没有给出维护者确认的统一根因,先核对主机和镜像架构,不要直接改入口脚本:
uname -m
docker image inspect weishaw/sub2api:0.1.183 \
--format '{{.Architecture}}/{{.Os}}'
docker compose --env-file .env -f compose.yaml logs --tail=100 sub2api官方镜像文档声明支持 linux/amd64 和 linux/arm64。架构不匹配或旧镜像残留时,删除有问题的单个标签后重新拉取固定版本,不要执行全局镜像清理。
修改 Redis 密码后没有生效
Issue #2511 描述过更新 .env 后 Redis 容器没有按预期应用密码的情况。当前 v0.1.183 Compose 已在启动命令中根据 REDIS_PASSWORD 追加 --requirepass,但修改密码后仍应强制重建 Redis 和应用容器:
docker compose --env-file .env -f compose.yaml up -d \
--force-recreate redis sub2api
docker compose --env-file .env -f compose.yaml exec -T redis \
redis-cli ping不要只运行 docker compose restart;重启沿用原容器配置,不负责重新解析所有配置变化。
PostgreSQL 报 Operation not permitted
本地目录版已经给 PostgreSQL 挂载添加了 SELinux :Z 标签。出现权限错误时,先检查目录所有权、SELinux 审计日志和 Docker/内核版本:
ls -ld postgres_data
docker compose --env-file .env -f compose.yaml logs --tail=100 postgresIssue #6099 报告某些 CentOS 内核在默认 seccomp 下仍会失败,并用 seccomp:unconfined 绕过。但这会关闭容器系统调用过滤,issue 本身也把它标记为高风险。它只能作为隔离环境中的诊断手段,不能直接写入长期生产配置;更稳妥的处理是升级受支持的内核和 Docker,或改用命名卷验证问题是否来自宿主机绑定目录。
应用健康检查一直失败
docker compose --env-file .env -f compose.yaml ps
docker compose --env-file .env -f compose.yaml logs --tail=150 sub2api
docker compose --env-file .env -f compose.yaml exec -T postgres \
pg_isready -U sub2api -d sub2api
docker compose --env-file .env -f compose.yaml exec -T redis \
redis-cli pingSub2API 依赖 PostgreSQL 和 Redis 健康后才启动。优先检查 .env 中的数据库密码、数据目录权限和迁移日志;不要反复删除数据目录来尝试“重新初始化”。
部署完成后
部署通过后,先完成 HTTPS、源站隔离和异地备份,再接入真实上游账号。随后创建一个低权限测试用户和独立 API Key,用一次小请求验证认证、路由、用量记录和流式响应;管理账号不要直接交给普通调用方使用。
总结
本文以 Sub2API 0.1.183 的版本固定 Compose 文件为基础,给出单机自托管所需的密钥生成、持久化、健康检查、数据库备份、恢复演练和升级边界。文章完成了官方资料核对与 Compose 静态解析,但没有在当前环境拉取镜像或启动容器;正式接入真实上游账号前,仍需在目标服务器验证 HTTPS、源站隔离、备份恢复和一条低成本 API 请求。
参考资料
- Sub2API GitHub 仓库 - 核对日期:2026-08-26
- Sub2API 0.1.183 Release - 发布日期:2026-08-25
- v0.1.183 Docker 部署说明 - 核对 Compose 路线、自动初始化、迁移和运维命令
- v0.1.183 本地目录 Compose - 核对服务、镜像、端口、健康检查和持久化目录
- v0.1.183 环境变量示例 - 核对密钥、日志、连接池和安全默认值
- Docker 镜像说明 - 核对镜像名称、标签策略和支持架构
- 边缘入口安全说明 - 核对 SSE、WebSocket、可信代理和 CDN/WAF 边界
- Issue #2061:exec format error - 仅作为架构类故障线索
- Issue #2511:Redis 密码更新 - 仅作为容器重建故障线索
- Issue #6099:CentOS 下 PostgreSQL 权限错误 - 仅作为高风险 seccomp 绕过案例