Bencher Docker Compose 部署指南
自定义 docker-compose.yml 部署 Bencher v0.6.13 自托管版:显式 project name、自定义 bridge 网络、bind mount 数据与配置、生产级反向代理、SQLite 备份恢复与等价 docker run 参考。
Bencher v0.6.13 Docker Compose 部署指南
目标:用自定义 docker-compose.yml 在 Ubuntu 22.04 单机部署 Bencher v0.6.13 自托管版,包含显式 project name、自定义网桥、bind mount 数据目录、API Server bencher.json 配置、Console 环境变量、生产级反向代理、以及等价
docker run参考命令。compose 已在本实验环境实测拉起:API 返回 {"version":"0.6.13"}、Console 返回 HTTP 200。
一、环境信息
| 项 | 值 |
|---|---|
| Bencher | v0.6.13(2026-09-28) |
| 镜像仓库 | ghcr.io/bencherdev |
| API 镜像 | ghcr.io/bencherdev/bencher-api:v0.6.13 |
| Console 镜像 | ghcr.io/bencherdev/bencher-console:v0.6.13 |
| Compose Project | bencher-0613-stack(显式 name:) |
| 网络 | bencher-0613-net(自定义 user-defined bridge) |
| API 端口 | 6610(host → container) |
| Console 端口 | 3000(host → container) |
| API 数据目录 | ./services/api/data → /var/lib/bencher/data |
| API 配置目录 | ./services/api/etc → /etc/bencher |
二、镜像选型说明
| 镜像 | 大小 | 说明 |
|---|---|---|
ghcr.io/bencherdev/bencher-api:v0.6.13 | 约 45 MB | Rust 编译静态链接,无多余依赖。必须带明确版本 tag;latest 可能和你本机 CLI 版本漂移。 |
ghcr.io/bencherdev/bencher-console:v0.6.13 | 约 80 MB | Next.js 构建产物 + Node 运行时,只读静态前端,配置靠环境变量。 |
⚠️ ghcr.io 拉取有匿名速率限制。如果
docker pull报 401/403,先docker logout ghcr.io清 token 再重试;高频拉取建议走代理(docker pull --help不支持代理 env,需要 daemon~/.docker/config.json配置)。
三、前置条件
- Docker Engine ≥ 20.10 + Compose 插件 ≥ v2.0
- 端口 3000、6610 未占用(
ss -ltn或lsof -i :3000检查) - IPv4 子网段可用(
docker network ls查已用的 user-defined bridge subnet,选空闲段)
四、部署步骤
4.1 创建目录结构
mkdir -p /opt/bencher-stack/{services/api/{etc,data},services/console,config}
# /opt/bencher-stack/
# ├── docker-compose.yml
# ├── services/api/etc/bencher.json # API Server 配置(可选)
# ├── services/api/data/bencher.db # SQLite(首次拉容器自动创建)
# └── services/console/ # Console 无状态,无需挂载
4.2 编写 docker-compose.yml
核心点:
- 显式
name: bencher-0613-stack作为 project name——避免多组件 compose 目录同名时互相覆盖(S7 批次教训)。 - 自定义 bridge 网络,显式 subnet 从批次空闲池取(本批次已用 56 段,选其他空闲段如 58)。
- api 和 console 都加入同一自定义网络,否则
INTERNAL_API_URL=http://bencher_api_compose:6610解析不到容器名。 - API Server 配置目录挂到
/etc/bencher,让容器读bencher.json;数据目录挂到/var/lib/bencher/data,SQLite 持久化。
# /opt/bencher-stack/docker-compose.yml
name: bencher-0613-stack
services:
bencher_api_compose:
image: ghcr.io/bencherdev/bencher-api:v0.6.13
container_name: bencher_api
restart: unless-stopped
ports:
- "6610:6610"
volumes:
- "./services/api/etc:/etc/bencher"
- "./services/api/data:/var/lib/bencher/data"
environment:
# 如果不挂配置文件,可以用环境变量直接内联 JSON
# - BENCHER_CONFIG={"server":{"bind_address":"0.0.0.0:6610"},"database":{"file":"/var/lib/bencher/data/bencher.db"}}
# 或者指向 JSON 文件路径
# - BENCHER_CONFIG_PATH=/etc/bencher/bencher.json
networks:
- bencher_net
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:6610/v0/server/version"]
interval: 30s
timeout: 5s
retries: 5
start_period: 10s
bencher_console_compose:
image: ghcr.io/bencherdev/bencher-console:v0.6.13
container_name: bencher_console
restart: unless-stopped
ports:
- "3000:3000"
environment:
- BENCHER_API_URL=http://127.0.0.1:6610
# 关键!Console 容器调 API 容器的地址(容器内 Docker-to-Docker 通信)
# 只在 Docker 网络中需要,指向 API 容器名 + 内部端口
- INTERNAL_API_URL=http://bencher_api_compose:6610
depends_on:
bencher_api_compose:
condition: service_healthy
networks:
- bencher_net
networks:
bencher_net:
name: bencher-0613-net
driver: bridge
ipam:
config:
- subnet: 10.89.58.0/24
4.3 拉镜像并拉起
cd /opt/bencher-stack
# 显式 --project-name 覆盖 compose 文件名推导的默认 project name
docker compose -p bencher-0613-stack up -d --pull always
# 查看状态
docker compose -p bencher-0613-stack ps
# NAME IMAGE STATUS PORTS
# bencher_api ghcr.io/bencherdev/bencher-api:v0.6.13 Up 5 minutes 0.0.0.0:6610->6610/tcp
# bencher_console ghcr.io/bencherdev/bencher-console:... Up 5 minutes 0.0.0.0:3000->3000/tcp
4.4 首启验证
# API Server 版本(鉴权未配置时,此路由公开)
curl -s http://localhost:6610/v0/server/version
# {"version":"0.6.13"}
# API Server OpenAPI spec 头
curl -s http://localhost:6610/v0/server/spec | head -c 200
# {"components":{"responses":{"Error":{"...
# Console 前端
curl -s -o /dev/null -w "HTTP %{http_code}\n" http://localhost:3000/
# HTTP 200
# 一键生成 mock 数据 + Claim(可选,验证全链路)
# 先在同一网段/机器装 CLI
# 然后:
# bencher mock --project demo --branch main --testbed local
# 浏览器打开 Claim 链接 → 注册即可
4.5 生产级反向代理(可选,推荐)
自托管版 Console 走纯 HTTP,外层套 nginx/caddy 做 HTTPS 很常见。下面给一个 nginx 反代模板:
server {
listen 80;
listen [::]:80;
server_name bencher.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name bencher.example.com;
ssl_certificate /etc/letsencrypt/live/bencher.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/bencher.example.com/privkey.pem;
# Console 前端
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
# API Server(/v0/... 和 /v2/... 都转发)
location /v0/ {
proxy_pass http://127.0.0.1:6610;
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;
# WebSocket 升级(bare metal runner 心跳)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# OCI Registry 路由(如果启用)
location /v2/ {
proxy_pass http://127.0.0.1:6610;
# 同上 Upgrade 头
}
}
⚠️ 走外层反代时,API Server 的
console.url必须改成公开域名(见 C1 篇console.url字段),否则 WebSocket 心跳会报 Origin mismatch。
五、数据持久化说明
| 路径 | 挂载到容器 | 容器内 | 内容 |
|---|---|---|---|
./services/api/data | ✅ | /var/lib/bencher/data | SQLite 数据库文件 bencher.db + WAL + 可选 registry/ |
./services/api/etc | ✅ | /etc/bencher | API Server 配置 bencher.json |
| Console | ❌ | 无数据 | Next.js 静态前端,纯只读 |
SQLite 备份与恢复
# 备份:停 API → 直接拷 db 文件(SQLite WAL 模式下需 checkpoint 或锁)
docker compose -p bencher-0613-stack stop bencher_api_compose
cp services/api/data/bencher.db /backup/bencher-$(date +%F).db
docker compose -p bencher-0613-stack start
# 恢复:停 API → 覆盖文件 → 启动
docker compose -p bencher-0613-stack stop bencher_api_compose
cp /backup/bencher-2026-10-27.db services/api/data/bencher.db
docker compose -p bencher-0613-stack start
curl -s http://localhost:6610/v0/server/version
Plus 版可以启用 Litestream 做 S3 连续复制(见 C1 篇 plus.disaster_recovery 字段)。
六、环境变量表
Console 容器环境变量(environment: 下)
| 变量 | 默认 | 必填 | 说明 |
|---|---|---|---|
BENCHER_API_URL | http://localhost:6610 | ✅(自托管生产必须改) | 浏览器访问 Console 时,前端 JS 用这个地址调 API。如果走外层反代,应该是 https://bencher.example.com。 |
INTERNAL_API_URL | 不设置 | 条件必填 | 只在 Docker 内部网络通信时需要,指向 API 容器名 + 内部端口:http://bencher_api_compose:6610。不要对远程 API 设置这个(如 Cloud)。 |
SERVER_KEY_PATH | 无 | ❌ | Console 自配 TLS 的私钥路径(不推荐,建议外层 nginx) |
SERVER_CERT_PATH | 无 | ❌ | Console 自配 TLS 的证书路径 |
OAUTH_GITHUB / OAUTH_GOOGLE | 不设置 | ❌ | Plus Enterprise 版 SSO 开关 |
API Server 容器环境变量(environment: 下)
| 变量 | 默认 | 必填 | 说明 |
|---|---|---|---|
BENCHER_CONFIG | 不设置 | ❌ | 内联 JSON 配置字符串 |
BENCHER_CONFIG_PATH | 不设置 | ❌ | JSON 配置文件路径(容器内) |
💡 优先级:
BENCHER_CONFIG>BENCHER_CONFIG_PATH>/etc/bencher/bencher.json> 默认配置。C1 篇给出了完整 JSON 字段表。
七、配置参数说明
API Server 的 bencher.json 可以挂载到 /etc/bencher 让容器读取。下面给一个生产推荐模板(SQLite + Plus 版 SSO + Litestream 灾难恢复,不含敏感值):
{
"console": { "url": "https://bencher.example.com" },
"security": {
"issuer": "https://api.bencher.example.com",
"secret_key": "CHANGE_ME_UJu7Cpxb-zFaJYqXD-3mDDSDyj-ZvfxZFZs-X58xjxPy"
},
"server": {
"bind_address": "0.0.0.0:6610",
"request_body_max_bytes": 10485760
},
"logging": {
"name": "Bencher API",
"log": { "stderr_terminal": { "level": "info" } }
},
"database": {
"file": "/var/lib/bencher/data/bencher.db",
"busy_timeout": 15000,
"cache_size": 131072
}
}
💡
secret_key是 JWT 签名密钥,首次启动时自动生成 UUID v4 并打码显示(************),千万不能丢——丢了意味着所有已发 JWT 全部失效,用户需要重新登录。
八、配置文件挂载
# compose 片段
services:
bencher_api_compose:
volumes:
- "./services/api/etc:/etc/bencher" # ← 放 bencher.json
- "./services/api/data:/var/lib/bencher/data"
首次启动前如果 etc/ 目录是空的,容器会用内置默认配置(API bind 0.0.0.0:6610、SQLite 路径对、secret_key 自动生成 UUID)——足够 PoC。
九、等价 docker run
不想走 compose,直接 docker run 也能拉起:
docker network create bencher-0613-net --driver bridge
# API Server
docker run -d \
--name bencher_api \
--network bencher-0613-net \
-p 6610:6610 \
-v /opt/bencher-stack/services/api/etc:/etc/bencher \
-v /opt/bencher-stack/services/api/data:/var/lib/bencher/data \
--restart unless-stopped \
ghcr.io/bencherdev/bencher-api:v0.6.13
# Console Server
docker run -d \
--name bencher_console \
--network bencher-0613-net \
-p 3000:3000 \
-e BENCHER_API_URL=http://127.0.0.1:6610 \
-e INTERNAL_API_URL=http://bencher_api:6610 \
--restart unless-stopped \
ghcr.io/bencherdev/bencher-console:v0.6.13
curl -s http://localhost:6610/v0/server/version
# {"version":"0.6.13"}
十、常用运维命令
# 查看所有容器状态
docker compose -p bencher-0613-stack ps
# 实时日志
docker compose -p bencher-0613-stack logs -f bencher_api_compose
docker compose -p bencher-0613-stack logs -f bencher_console_compose
# 也可以用 CLI(封装了上面这条)
bencher logs --detach=false # ⚠️ 官方 CLI 也提供 logs 子命令
# 进入容器排障
docker exec -it bencher_api bash
# 停止并保留容器
docker compose -p bencher-0613-stack stop
# 停止 + 删容器(数据目录保留)
docker compose -p bencher-0613-stack down
# 停止 + 删容器 + 删数据卷(⚠️ 不可逆)
docker compose -p bencher-0613-stack down -v
# 升级:改 compose image tag → down → pull → up
sed -i 's/v0\.6\.13/v0.6.14/g' docker-compose.yml
docker compose -p bencher-0613-stack down
docker compose -p bencher-0613-stack pull
docker compose -p bencher-0613-stack up -d
十一、常见问题
Q1:bencher_console 启动报错 "ECONNREFUSED http://bencher_api_compose:6610"?
两个容器没在同一网络或 API 容器还没起来。检查 compose 里两个 service 的 networks: 段,以及 depends_on.condition 是否设为 service_healthy。
Q2:Console 能打开,但跑 mock/run 时 API 401?
API Server 默认 无鉴权(第一次启动时没有用户/项目)。bencher run/mock 会自动创建临时 project,只要 Console 和 API 在同一 network 且端口配对正确就能通。401 通常意味着你自己配置了 SMTP 或 SSO 但没配对。
Q3:改了 Console 端口(--console-port 13000)但 API 还是打 3000?
必须同步改 bencher.json 的 console.url,或者 bencher up --api-env 传进去。两个必须一起改。
Q4:API Server 的 SQLite 会不会锁死?
SQLite WAL 模式下多写者排队,busy_timeout 默认 5s 超时会报 database is locked。高并发场景下调大到 15s 并把 cache_size 翻倍(见 C1 篇 database 字段表)。
Q5:compose up 后拉不到镜像?
ghcr.io 匿名限流。docker logout ghcr.io 清 token 再试;或者配 daemon HTTP proxy(~/.docker/config.json):
{
"proxies": {
"ghcr.io": {
"httpProxy": "http://192.168.1.62:7897",
"httpsProxy": "http://192.168.1.62:7897"
}
}
}
十二、参考链接
- Bencher Compose 官方模板:https://bencher.dev/docs/reference/bencher-compose/
- Self-Hosted 教程:https://bencher.dev/docs/tutorial/self-hosted/
- API Server 配置:https://bencher.dev/docs/reference/server-config/
- Console Server 配置:https://bencher.dev/docs/reference/console-config/