文档

Deployment

Codex2API
Docker Compose 一键部署

适用于已经安装 Docker Engine 与 Docker Compose v2 的 Linux 服务器。默认公开监听 8080 端口,数据保存在 Docker 命名卷中。

执行前

  • 终端使用能执行 Bash 的 SSH 会话
  • 运行时Docker Engine 与 docker compose
  • 网络服务器防火墙或安全组放行 TCP 8080

SSH

完整部署命令

bash <<'CODEX2API_DEPLOY'
set -Eeuo pipefail

APP_DIR="${APP_DIR:-$HOME/codex2api}"
PORT="${PORT:-8080}"
BIND_HOST="${BIND_HOST:-0.0.0.0}"
TIMEZONE="${TIMEZONE:-Asia/Shanghai}"
IMAGE="${IMAGE:-ghcr.io/james-6-23/codex2api:latest}"
WAIT_SECONDS="${WAIT_SECONDS:-120}"

fail() {
  printf '[FAIL] %s\n' "$*" >&2
  exit 1
}

random_hex() {
  local bytes="$1"
  if command -v openssl >/dev/null 2>&1; then
    openssl rand -hex "$bytes"
  else
    od -An -N "$bytes" -tx1 /dev/urandom | tr -d ' \n'
  fi
}

env_value() {
  local key="$1"
  sed -n "s/^${key}=//p" .env | head -n 1
}

command -v docker >/dev/null 2>&1 || fail "未找到 Docker Engine"
docker info >/dev/null 2>&1 || fail "Docker daemon 未运行,或当前用户没有权限"
docker compose version >/dev/null 2>&1 || fail "需要 Docker Compose v2"
command -v curl >/dev/null 2>&1 || fail "未找到 curl"
[[ "$PORT" =~ ^[0-9]+$ ]] && (( PORT >= 1 && PORT <= 65535 )) || fail "PORT 必须是 1-65535"

umask 077
mkdir -p "$APP_DIR/logs"
cd "$APP_DIR"
APP_DIR="$(pwd -P)"

if [[ -f .env ]]; then
  printf '[INFO] 保留现有配置:%s/.env\n' "$APP_DIR"
else
  ADMIN_SECRET="adm_$(random_hex 24)"
  IMAGE_ASSET_SIGNING_SECRET="$(random_hex 32)"
  cat > .env <<ENV_FILE
BIND_HOST=$BIND_HOST
CODEX_PORT=$PORT
CODEX_BIND=0.0.0.0
ADMIN_SECRET=$ADMIN_SECRET
CODEX_ALLOW_ANONYMOUS=false
DATABASE_DRIVER=sqlite
DATABASE_PATH=/data/codex2api.db
CACHE_DRIVER=memory
IMAGE_ASSET_DIR=/data/images
IMAGE_ASSET_SIGNING_SECRET=$IMAGE_ASSET_SIGNING_SECRET
LOG_DIR=/app/logs
LOG_DISABLED=false
TZ=$TIMEZONE
CODEX2API_IMAGE=$IMAGE
ENV_FILE
  chmod 600 .env
fi

cat > docker-compose.yml <<'COMPOSE_FILE'
name: codex2api-sqlite

services:
  codex2api:
    image: "${CODEX2API_IMAGE:-ghcr.io/james-6-23/codex2api:latest}"
    container_name: codex2api-sqlite
    restart: unless-stopped
    env_file:
      - .env
    ports:
      - "${BIND_HOST:-0.0.0.0}:${CODEX_PORT:-8080}:${CODEX_PORT:-8080}"
    volumes:
      - codex2api-data:/data
      - ./logs:/app/logs
    logging:
      driver: json-file
      options:
        max-size: 20m
        max-file: "5"
    security_opt:
      - no-new-privileges:true

volumes:
  codex2api-data:
    name: codex2api-sqlite_sqlite-data
COMPOSE_FILE
chmod 600 docker-compose.yml

docker compose config --quiet
docker compose pull
docker compose up -d --remove-orphans

ACTIVE_PORT="$(env_value CODEX_PORT)"
ACTIVE_BIND="$(env_value BIND_HOST)"
ACTIVE_PORT="${ACTIVE_PORT:-8080}"
ACTIVE_BIND="${ACTIVE_BIND:-0.0.0.0}"
PROBE_HOST="$ACTIVE_BIND"
[[ "$PROBE_HOST" == "0.0.0.0" ]] && PROBE_HOST="127.0.0.1"
HEALTH_URL="http://${PROBE_HOST}:${ACTIVE_PORT}/health"

printf '[INFO] 等待健康检查:%s\n' "$HEALTH_URL"
deadline=$((SECONDS + WAIT_SECONDS))
until curl --fail --silent --show-error --max-time 4 --output /dev/null "$HEALTH_URL"; do
  if (( SECONDS >= deadline )); then
    docker compose logs --tail=120 codex2api >&2 || true
    fail "${WAIT_SECONDS} 秒内健康检查未通过"
  fi
  if [[ "$(docker inspect --format '{{.State.Running}}' codex2api-sqlite 2>/dev/null || true)" != "true" ]]; then
    docker compose logs --tail=120 codex2api >&2 || true
    fail "容器已退出"
  fi
  sleep 2
done

DISPLAY_HOST="$ACTIVE_BIND"
if [[ "$DISPLAY_HOST" == "0.0.0.0" ]]; then
  DISPLAY_HOST="${SERVER_IP:-$(hostname -I 2>/dev/null | awk '{print $1}')}"
  DISPLAY_HOST="${DISPLAY_HOST:-<服务器IP>}"
fi

printf '\n[OK] Codex2API 已部署并通过健康检查\n'
printf '部署目录:%s\n' "$APP_DIR"
printf '管理后台:http://%s:%s/admin/\n' "$DISPLAY_HOST" "$ACTIVE_PORT"
printf 'API Base URL:http://%s:%s/v1\n' "$DISPLAY_HOST" "$ACTIVE_PORT"
printf '管理密码:%s\n' "$(env_value ADMIN_SECRET)"
printf '首次登录后,请在“API Keys”页面创建调用密钥。\n'
CODEX2API_DEPLOY

部署完成后

管理后台http://服务器IP:8080/admin/
健康检查http://服务器IP:8080/health
API 地址http://服务器IP:8080/v1

脚本会在终端显示随机管理密码。首次登录后台后,在“API Keys”页面创建调用密钥;匿名 API 访问保持关闭。

常用维护命令

查看日志cd ~/codex2api && docker compose logs -f codex2api
拉取更新cd ~/codex2api && docker compose pull && docker compose up -d
停止服务cd ~/codex2api && docker compose down

停止服务不要附加 -v;命名卷承载 SQLite 数据、图库与持久化配置。