修复:补充 Linux Docker 主机映射

This commit is contained in:
zhang,zhao
2026-07-14 17:33:55 +08:00
parent 46338f4435
commit 8a6c85bfc8
3 changed files with 2 additions and 140 deletions
+2
View File
@@ -11,6 +11,8 @@ services:
container_name: TickFlow_Stock_Panel
ports:
- "${PORT:-3018}:3018"
extra_hosts:
- "host.docker.internal:host-gateway"
env_file:
- .env
environment:
@@ -1,68 +0,0 @@
# Docker Codex CLI Support Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Make Docker deployments detect and execute the host-authenticated Codex CLI without putting credentials into the image.
**Architecture:** Install a pinned `@openai/codex` package in a dedicated Node builder stage, extract its platform-native Linux binary, and copy only that binary into the runtime image. Mount `${HOME}/.codex` read-only so the existing backend can copy authentication into its per-request temporary Codex home.
**Tech Stack:** Docker multi-stage builds, Docker Compose, `@openai/codex`, FastAPI, pytest
---
### Task 1: Establish baseline and impact
**Files:** No changes.
- [x] Confirm host `codex --version` reports `0.144.3`.
- [x] Confirm the old container cannot resolve `codex`.
- [x] Run GitNexus impact on `_resolve_command`; avoid changing the HIGH-risk backend symbol chain.
- [x] Run `uv run pytest tests/test_ai_provider.py -q`; expect 15 passing tests.
### Task 2: Package Codex in Docker
**Files:**
- Modify: `Dockerfile`
- [x] Add `CODEX_CLI_VERSION=0.144.3` as a reproducible build argument.
- [x] Install `@openai/codex` in `codex-builder` and locate `*/vendor/*/bin/codex`.
- [x] Copy the native binary to `/opt/codex-native` and verify its version in the builder.
- [x] Copy only `/opt/codex-native` to runtime `/usr/local/bin/codex` and verify it there.
- [x] Keep runtime Node.js conditional on stock-sdk because the extracted Codex binary is self-contained.
### Task 3: Reuse host authentication safely
**Files:**
- Modify: `docker-compose.yml`
- [x] Pass `CODEX_CLI_VERSION` through Compose.
- [x] Mount `${HOME}/.codex:/root/.codex:ro`.
- [x] Set `CODEX_DOCKER_HOST=host.docker.internal` for loopback local-access providers.
- [x] Run `docker compose config` and confirm the version and read-only mount.
### Task 4: Document behavior
**Files:**
- Modify: `README.md`
- Create: `docs/superpowers/plans/2026-07-14-docker-codex-cli.md`
- [x] Document the pinned version, version override, host login requirement, and credential security boundary.
- [ ] Run `git diff --check`.
- [ ] Run `gitnexus detect-changes` before the documentation commit.
### Task 5: End-to-end verification and PR
**Files:** No changes.
- [x] Build the Codex builder stage and verify `codex-cli 0.144.3`.
- [x] Copy the extracted binary into the current TickFlow runtime image and verify it executes without Node.js.
- [x] Add red/green tests for opt-in local-access provider mapping and default token isolation.
- [x] Recreate the app with the Codex-enabled image and existing data.
- [x] Verify `/api/settings` reports Codex configured.
- [x] POST `/api/strategies/ai/test` and receive `{"ok":true}` with `OK`.
- [ ] Re-run provider tests and inspect final Git/GitNexus scope.
- [ ] Push `codex/docker-codex-cli` and open a Draft PR against `main`.
### Known external build issue
A cold full-image build currently reaches the Codex stages successfully, then fails in the pre-existing backend dependency layer because `backend/uv.lock` contains direct Tsinghua mirror wheel URLs returning HTTP 403. This PR does not rewrite the lockfile or mix that unrelated dependency-source problem into the Codex fix; runtime compatibility is verified separately against the existing TickFlow image.
@@ -1,72 +0,0 @@
# Docker 模式支持 Codex CLI 设计
## 背景
TickFlow 的 Docker 服务运行在独立容器中。即使 macOS 主机已经安装并登录 Codex CLI,容器内的 `shutil.which("codex")` 仍无法找到主机命令,因此设置页显示“未找到 Codex CLI 命令: codex”。
## 目标
- Docker 镜像内提供可直接执行的 `codex` 命令。
- 复用主机已有的 Codex 登录凭据,无需在容器内重复交互式登录。
- 保持现有 `codex exec`、临时工作目录、只读沙箱和隔离 `CODEX_HOME` 逻辑不变。
- 保持镜像构建可复现,并允许维护者显式升级 Codex CLI 版本。
## 非目标
- 不允许用户配置任意可执行文件路径。
- 不改变本机开发模式和桌面客户端的 Codex 命令解析逻辑。
- 不把 Codex 凭据复制进镜像或提交到仓库。
- 不为 Dockerfile 文本结构增加脆弱的单元测试。
## 方案
### 镜像构建
Dockerfile 新增独立的 `codex-builder` 阶段,使用 Node bookworm 镜像安装固定版本的 `@openai/codex`,再从官方包中提取当前构建平台的 Linux 原生二进制。版本由 `CODEX_CLI_VERSION` 构建参数控制,并提供项目验证过的默认值。
运行阶段只把提取后的原生二进制复制到 `/usr/local/bin/codex`,不复制 npm 包,也不要求为了 Codex 常驻安装 Node.js。这样保留多架构构建能力,同时减少运行层体积和可变依赖。
### 凭据挂载
`docker-compose.yml` 将主机 `${HOME}/.codex` 挂载到容器 `/root/.codex`,模式为只读。挂载目录不会写入镜像或仓库。
后端现有 `_prepare_codex_home` 会从只读挂载中读取 `auth.json` 和兼容配置,再复制或生成到单次请求的临时 `CODEX_HOME`。Codex 子进程只使用临时目录,因此不会修改主机凭据目录。
当主机配置明确选择 `codex_local_access` 时,Compose 通过 `CODEX_DOCKER_HOST=host.docker.internal` 启用受控适配:临时配置只复制该 provider 的必要白名单字段,将 `localhost``127.0.0.1``::1` 改为 Docker host gateway,并保留原端口。未设置该环境变量时继续使用原有隔离配置,不复制 provider 或 bearer token。
### 数据流
1. Compose 启动容器并只读挂载主机 Codex home。
2. 设置接口调用 `codex_cli_available()`
3. `_resolve_command("codex")` 在容器 PATH 中找到镜像内入口。
4. 发起 AI 请求时,后端建立临时工作区和临时 `CODEX_HOME`
5. 后端复用挂载目录中的认证信息并执行 `codex exec`
6. 请求结束后临时目录自动删除。
## 错误处理
- 主机未安装 Codex 不影响容器命令,因为 CLI 已包含在镜像中。
- 主机未登录或 `${HOME}/.codex/auth.json` 不存在时,设置页仍可识别 CLI;实际调用会返回现有的 Codex 登录错误。
- 构建时无法下载指定 npm 包时,镜像构建应失败,不静默切换到不固定版本。
- 挂载目录保持只读;任何意外写入都会由容器文件系统拒绝。
## 安全性
- Codex home 仅以只读方式挂载。
- 凭据不进入 Docker build context 的产物层。
- local-access bearer token 仅从只读主机配置复制到单次请求的临时配置,且只在 Docker 显式启用适配时发生。
- 现有 `--ephemeral``--sandbox read-only``approval_policy = "never"` 和空白临时工作区保持不变。
- 文档明确说明:启用 Docker Codex 模式意味着 TickFlow 容器能够读取 Codex 登录凭据,应仅在受信任的本机环境使用。
## 验证
1. 构建镜像成功。
2. 容器内 `command -v codex` 返回 `/usr/local/bin/codex`
3. 容器内 `codex --version` 返回设计中固定的版本。
4. 设置接口返回 `ai_configured: true`,页面不再显示“未找到 Codex CLI 命令”。
5. 执行一次真实连接测试,确认 `codex exec` 能读取认证并返回内容。
6. 运行现有后端 AI provider 测试,确认非 Docker 路径无回归。
## 文档更新
README 的 Docker 启动说明增加 Codex CLI 凭据挂载、安全边界和版本覆盖方式,避免用户把“主机已安装”误认为“容器自动可见”。