CLIProxyAPI Zeabur 部署:配置文件持久化方案

问题背景

在 Zeabur 上部署 CLIProxyAPI 时,容器启动后崩溃,报错如下:

[error] [main.go:391] failed to load config: failed to read config file: open /CLIProxyAPI/config.yaml: no such file or directory

原因分析

直接原因

Dockerfile 中只将 config.example.yaml 复制到了容器的 /CLIProxyAPI/ 目录,但程序启动时在工作目录下查找的是 config.yaml,文件不存在导致启动失败。

相关代码逻辑

程序的配置加载逻辑位于 cmd/server/main.go,当没有配置任何外部存储(PostgreSQL / Git / Object Store),也没有通过 --config 参数指定路径时,默认在当前工作目录拼接 config.yaml

// cmd/server/main.go:386-392
wd, err = os.Getwd()
if err != nil {
    log.Errorf("failed to get working directory: %v", err)
    return
}
configFilePath = filepath.Join(wd, "config.yaml")
cfg, err = config.LoadConfigOptional(configFilePath, isCloudDeploy)

LoadConfigOptional 的第二个参数 optional 控制是否允许配置文件缺失。只有当环境变量 DEPLOY=cloudisCloudDeploytrue,此时文件不存在不会报错。默认情况下 optional=false,文件缺失直接返回错误。

修复方案

快速修复:让容器启动时有默认配置

在 Dockerfile 中将 config.example.yaml 同时复制为 config.yaml

COPY config.example.yaml /CLIProxyAPI/config.yaml

这能解决启动崩溃,但容器重启后所有修改过的配置和登录的 Token 都会丢失。

持久化方案:挂载本地卷到 /data

修改 Dockerfile 的 CMD,将配置和认证数据指向持久化卷:

CMD ["sh", "-c", "mkdir -p /data/auths && if [ ! -f /data/config.yaml ]; then sed 's|auth-dir:.*|auth-dir: \"/data/auths\"|' /CLIProxyAPI/config.example.yaml > /data/config.yaml; fi && exec ./CLIProxyAPI --config /data/config.yaml"]

启动时的行为:

  1. 确保 /data/auths 目录存在
  2. /data/config.yaml 不存在(首次部署),从模板复制并将 auth-dir 改为 /data/auths
  3. 若已存在(重启),直接使用现有配置
  4. 通过 --config /data/config.yaml 让程序从持久卷读取配置

在 Zeabur 中将卷挂载到 /data 即可,持久化内容包括:

  • /data/config.yaml -- 服务器配置
  • /data/auths/ -- 登录 Token 文件

完整 Dockerfile

FROM golang:1.26-alpine AS builder

WORKDIR /app

COPY go.mod go.sum ./

RUN go mod download

COPY . .

ARG VERSION=dev
ARG COMMIT=none
ARG BUILD_DATE=unknown

RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w -X 'main.Version=${VERSION}' -X 'main.Commit=${COMMIT}' -X 'main.BuildDate=${BUILD_DATE}'" -o ./CLIProxyAPI ./cmd/server/

FROM alpine:3.22.0

RUN apk add --no-cache tzdata

RUN mkdir /CLIProxyAPI

COPY --from=builder ./app/CLIProxyAPI /CLIProxyAPI/CLIProxyAPI

COPY config.example.yaml /CLIProxyAPI/config.example.yaml

WORKDIR /CLIProxyAPI

EXPOSE 8317

ENV TZ=Asia/Shanghai

RUN cp /usr/share/zoneinfo/${TZ} /etc/localtime && echo "${TZ}" > /etc/timezone

CMD ["sh", "-c", "mkdir -p /data/auths && if [ ! -f /data/config.yaml ]; then sed 's|auth-dir:.*|auth-dir: \\"/data/auths\\"|' /CLIProxyAPI/config.example.yaml > /data/config.yaml; fi && exec ./CLIProxyAPI --config /data/config.yaml"]

其他持久化方案

项目还内置了三种远程持久化存储,通过环境变量启用,优先级为 PostgreSQL > Git > Object Store > 本地文件。

Git 仓库存储

将配置和 Token 持久化到 Git 远程仓库,零成本方案。

GITSTORE_GIT_URL=https://github.com/用户名/私有仓库.git
GITSTORE_GIT_USERNAME=用户名
GITSTORE_GIT_TOKEN=GitHub PAT

S3/MinIO 对象存储

OBJECTSTORE_ENDPOINT=s3.amazonaws.com
OBJECTSTORE_ACCESS_KEY=AccessKey
OBJECTSTORE_SECRET_KEY=SecretKey
OBJECTSTORE_BUCKET=Bucket名

PostgreSQL 数据库

PGSTORE_DSN=postgres://用户:密码@主机:5432/数据库
PGSTORE_SCHEMA=自定义schema(可选)

Zeabur 自带 PostgreSQL 服务,可直接添加实例并使用连接字符串。