本文说明如何让 Windows 上的 Codex 桌面版通过 SSH 连接 WSL/Docker 中的 Ubuntu 编译容器,并在容器内读取代码、执行命令和使用编译工具。
1. 当前环境与最终结果
本次实际环境如下:
| 项目 | 实际值 |
|---|---|
| Codex 桌面端 | Windows |
| 容器系统 | Ubuntu 22.04(Jammy) |
| 容器用户 | root |
| Windows SSH 地址 | 127.0.0.1 |
| Windows SSH 端口 | 2200 |
| 容器 SSH 端口 | 22 |
| Windows 系统代理 | 127.0.0.1:7897 |
| Windows WSL 接口 | 172.18.240.1 |
| WSL 专用代理转发 | 172.18.240.1:7898 |
| 已安装 Codex CLI | 0.154.0 |
| Codex 安装位置 | /root/.local/bin/codex |
最终链路:
text
Windows Codex 桌面版
|
| SSH: root@127.0.0.1:2200
v
WSL / Docker Ubuntu 容器
|
| HTTPS 代理: 172.18.240.1:7898
v
Windows 本机代理: 127.0.0.1:7897
|
v
ChatGPT / OpenAI 服务
当前日志已经证明:
- SSH 端口可以连接,远端是 Ubuntu OpenSSH。
- 容器可以通过 Windows 代理访问
chatgpt.com。 - Codex CLI
0.154.0已成功安装。 codex --version已能返回版本号。
尚需在 Codex 桌面版中执行一次"重新连接",并确认远程项目可以正常打开,才能完成端到端验收。
2. 工作原理
Codex 桌面版不会直接操作 Docker API。它通过 Windows OpenSSH 连接远程主机,然后在远端用户的登录 shell 中启动 Codex App Server。
因此必须同时满足:
- Windows 能通过 SSH 登录容器。
- 容器内已安装 Codex CLI。
- 新的 SSH 登录 shell 能在
PATH中找到codex。 - 容器能够访问 ChatGPT/OpenAI 服务。
- 远端 Codex 已完成所需的身份验证。
3. 配置容器 SSH 服务
如果容器已经能通过 127.0.0.1:2200 登录,可跳到第 4 节。
3.1 安装 OpenSSH
在容器控制台中运行:
bash
apt-get update
apt-get install -y openssh-server ca-certificates curl git
mkdir -p /run/sshd
使用公钥认证,不建议启用 root 密码登录:
bash
cat >/etc/ssh/sshd_config.d/99-codex.conf <<'EOF'
PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin prohibit-password
EOF
/usr/sbin/sshd -t
启动 SSH 服务:
bash
pgrep -x sshd >/dev/null || /usr/sbin/sshd
ss -lntp | grep ':22'
3.2 Windows 生成 SSH 密钥
在普通 Windows PowerShell 中运行:
powershell
ssh-keygen -t ed25519 `
-f C:\Users\76778\.ssh\docker_wukun `
-C codex-docker
查看公钥:
powershell
Get-Content C:\Users\76778\.ssh\docker_wukun.pub
将完整的 ssh-ed25519 ... 一行加入容器:
bash
mkdir -p /root/.ssh
chmod 700 /root/.ssh
cat >>/root/.ssh/authorized_keys <<'EOF'
ssh-ed25519 AAAA... codex-docker
EOF
chmod 600 /root/.ssh/authorized_keys
chown -R root:root /root/.ssh
注意:Codex 配置中应选择私钥 docker_wukun,不要选择公钥 docker_wukun.pub。
3.3 发布容器 SSH 端口
创建容器时发布端口:
bash
docker run -d \
--name docker_wukun \
-p 127.0.0.1:2200:22 \
<你的镜像>
Compose 配置:
yaml
services:
build-env:
image: your-image
ports:
- "127.0.0.1:2200:22"
Docker 不能给已经创建的容器动态添加端口映射。若原容器没有映射 2200:22,需要按原镜像、卷挂载和环境变量重新创建。
4. 配置 Windows SSH 客户端
官方推荐先把远程主机写入 Windows 用户的 SSH 配置,让 Codex 自动发现明确的主机别名。
编辑:
text
C:\Users\76778\.ssh\config
添加:
sshconfig
Host docker_wukun
HostName 127.0.0.1
Port 2200
User root
IdentityFile C:/Users/76778/.ssh/docker_wukun
IdentitiesOnly yes
ServerAliveInterval 30
ServerAliveCountMax 3
在 PowerShell 验证:
powershell
ssh docker_wukun
也可以绕过 SSH 配置直接验证:
powershell
ssh -i C:\Users\76778\.ssh\docker_wukun `
-p 2200 root@127.0.0.1
常见结果:
| 输出 | 含义 |
|---|---|
成功进入 root@<容器ID> |
SSH 链路成功 |
Permission denied |
用户名、私钥或 authorized_keys 有误 |
Connection refused |
sshd 未启动或端口未映射 |
| 首次出现主机指纹确认 | 正常;确认目标确实是自己的容器后接受 |
5. 配置容器访问 Windows 代理
5.1 已确认的代理参数
Windows 用户代理配置显示:
text
ProxyEnable : 1
ProxyServer : 127.0.0.1:7897
netsh winhttp show proxy 显示"直接访问"不影响浏览器/用户代理。本场景使用的是代理软件监听的 7897,不是 WinHTTP 代理。
容器中的 127.0.0.1 指向容器自身,不能直接使用 127.0.0.1:7897。
本机已识别的地址:
text
Windows WLAN: 192.168.200.116
Windows WSL: 172.18.240.1
路由器网关: 192.168.200.1 # 不要使用
WSL 地址可能在 Windows/WSL 重启后变化。遇到连接问题时重新运行 ipconfig,不要永久假设它始终是 172.18.240.1。
5.2 查看代理监听状态
在 Windows PowerShell 中运行:
powershell
Get-NetTCPConnection -LocalPort 7897 -State Listen |
Select-Object LocalAddress, LocalPort, OwningProcess
判断方式:
127.0.0.1或::1:仅 Windows 本机可访问。0.0.0.0或:::其他接口也可访问。- 没有输出:代理软件未运行或端口不正确。
"Allow LAN / 允许局域网连接"是代理软件界面中的开关,不是 PowerShell 命令。
5.3 方案 A:使用代理软件的 Allow LAN
在代理软件设置中开启"允许局域网连接",然后从容器测试:
bash
unset HTTP_PROXY HTTPS_PROXY ALL_PROXY
unset http_proxy https_proxy all_proxy
curl -x http://172.18.240.1:7897 \
-4I --connect-timeout 15 https://chatgpt.com
若 WSL 地址不可用,再尝试 Windows WLAN 地址:
bash
curl -x http://192.168.200.116:7897 \
-4I --connect-timeout 15 https://chatgpt.com
本次日志中,这两个地址均成功建立了代理隧道。
注意:Allow LAN 可能把代理暴露给同一局域网。应使用 Windows 防火墙限制来源,或使用下一节的 WSL 专用转发。
5.4 方案 B:建立 WSL 专用代理转发
本次最终安装使用的是该方案:
text
172.18.240.1:7898 -> 127.0.0.1:7897
以管理员身份打开 Windows PowerShell:
powershell
netsh interface portproxy add v4tov4 `
listenaddress=172.18.240.1 listenport=7898 `
connectaddress=127.0.0.1 connectport=7897
仅允许 WSL 子网访问:
powershell
New-NetFirewallRule `
-DisplayName "WSL Proxy Relay 7898" `
-Direction Inbound `
-Action Allow `
-Protocol TCP `
-LocalAddress 172.18.240.1 `
-LocalPort 7898 `
-RemoteAddress 172.18.240.0/20
检查转发:
powershell
netsh interface portproxy show v4tov4
容器中测试:
bash
curl -x http://172.18.240.1:7898 \
-4I --connect-timeout 15 https://chatgpt.com
出现以下组合说明 HTTPS 代理隧道已经建立:
text
HTTP/1.1 200 Connection established
HTTP/2 403
cf-mitigated: challenge
这里的 403 是 Cloudflare 对简单 HEAD 请求的浏览器验证,不等于代理失败。后续安装脚本能够成功下载,才是最终网络验证。
若不再需要该转发,可在管理员 PowerShell 中删除:
powershell
netsh interface portproxy delete v4tov4 `
listenaddress=172.18.240.1 listenport=7898
Remove-NetFirewallRule -DisplayName "WSL Proxy Relay 7898"
6. 安装 Codex CLI
6.1 当前容器的安装方法
先为当前 shell 配置代理:
bash
unset HTTP_PROXY HTTPS_PROXY ALL_PROXY
unset http_proxy https_proxy all_proxy
export http_proxy=http://172.18.240.1:7898
export https_proxy=http://172.18.240.1:7898
export HTTP_PROXY="$http_proxy"
export HTTPS_PROXY="$https_proxy"
export NO_PROXY=localhost,127.0.0.1
export no_proxy="$NO_PROXY"
执行官方安装命令:
bash
curl -4fsSL https://chatgpt.com/codex/install.sh | sh
本次成功日志:
text
Installing Codex CLI
Detected platform: Linux (x64)
Resolved version: 0.154.0
Codex CLI 0.154.0 installed successfully.
验证:
bash
/root/.local/bin/codex --version
预期输出:
text
codex-cli 0.154.0
6.2 确保 SSH 登录 shell 能找到 Codex
Codex 桌面版要求远程登录 shell 的 PATH 中存在 codex。作为 root,可创建全局链接:
bash
ln -sf /root/.local/bin/codex /usr/local/bin/codex
command -v codex
codex --version
预期:
text
/usr/local/bin/codex
codex-cli 0.154.0
从 Windows 新建 SSH 会话验证,而不是只在安装时的旧 shell 中验证:
powershell
ssh docker_wukun "command -v codex && codex --version"
6.3 持久化代理变量
单纯执行 export 只对当前 shell 有效。Codex 桌面版重新 SSH 登录后可能无法联网,因此应让登录 shell 自动加载代理。
在容器中创建:
bash
cat >/etc/profile.d/codex-proxy.sh <<'EOF'
export http_proxy=http://172.18.240.1:7898
export https_proxy=http://172.18.240.1:7898
export HTTP_PROXY="$http_proxy"
export HTTPS_PROXY="$https_proxy"
export NO_PROXY=localhost,127.0.0.1
export no_proxy="$NO_PROXY"
EOF
chmod 644 /etc/profile.d/codex-proxy.sh
从 Windows 验证新的 SSH 登录 shell:
powershell
ssh docker_wukun "bash -lc 'env | grep -i proxy; codex --version'"
若 WSL 地址变化,需要同步更新:
- Windows
portproxy的listenaddress。 - Windows 防火墙规则的
LocalAddress和 WSL 子网。 - 容器
/etc/profile.d/codex-proxy.sh中的代理地址。
7. 完成 Codex 身份验证
在容器的交互式 SSH 会话中运行:
bash
codex
首次运行时,按照界面提示选择使用 ChatGPT 登录或其他可用认证方式。安装成功不代表身份验证已经完成;官方快速入门将"安装"和"登录"列为两个独立步骤。
完成后退出,再检查:
bash
codex --version
8. 在 Codex 桌面版添加连接
- 打开 Codex/ChatGPT 桌面版。
- 进入"设置 > 连接 > SSH"。
- 如果已配置
C:\Users\76778\.ssh\config,选择或添加docker_wukun。 - 启用连接。
- 如果显示失败,点击"重新连接"。
- 连接成功后,选择容器内的远程项目目录。
如果使用界面手动填写:
| 字段 | 值 |
|---|---|
| 名称 | docker_wukun |
| 主机 | 127.0.0.1 |
| 端口 | 2200 |
| 用户 | root(如果界面提供该字段) |
| 身份文件 | C:\Users\76778\.ssh\docker_wukun |
如果界面没有单独的"用户"字段,优先通过 SSH 配置中的 User root 提供,不要依赖 Windows 当前用户名。
9. 端到端验收
按顺序执行,全部通过才算配置完成。
9.1 Windows 到容器 SSH
powershell
ssh docker_wukun "id; hostname"
要求:返回 uid=0(root) 和容器主机名。
9.2 新 SSH 会话中的 Codex PATH
powershell
ssh docker_wukun "command -v codex && codex --version"
要求:返回 Codex 路径和版本。
9.3 新登录 shell 中的代理
powershell
ssh docker_wukun `
"bash -lc 'curl -4fsSL -o /dev/null -w \"%{http_code}\n\" https://chatgpt.com/codex/install.sh'"
要求:返回成功的 HTTP 状态码,并且没有连接超时或代理解析错误。
9.4 Codex 桌面连接
要求:
- 不再显示"SSH 连接失败"。
- 不再显示"远程计算机上未安装 Codex CLI"。
- 能够选择并打开容器内项目目录。
- 新聊天运行
pwd、git status或编译命令时,输出来自容器。
建议在远程聊天中执行:
text
运行 hostname、pwd、codex --version,并告诉我当前执行环境。
10. 常见错误对照
| 错误 | 原因 | 处理 |
|---|---|---|
SSH connection failed |
SSH 链路失败 | 用 ssh -vv docker_wukun 排查 |
Permission denied (publickey,password) |
用户或私钥不匹配 | 检查 User、IdentityFile、authorized_keys 权限 |
Connection refused(端口 2200) |
SSH 服务未启动或未映射端口 | 检查 sshd 和 2200:22 |
未安装 Codex CLI |
远端找不到 codex |
安装 CLI,并确保登录 shell 的 PATH 可见 |
codex: command not found |
CLI 未安装或 PATH 未加载 | 运行 /root/.local/bin/codex --version,再创建 /usr/local/bin/codex 链接 |
curl: (28) |
目标 443 连接超时 | 配置 Windows 代理和容器代理变量 |
Could not resolve proxy: host.docker.internal |
当前 Docker 环境没有该 DNS 别名 | 使用 WSL 地址 172.18.240.1 或实际 Windows IP |
192.168.200.1:7897 refused |
使用了路由器地址 | 使用 172.18.240.1 或 192.168.200.116 |
HTTP/2 403 cf-mitigated |
Cloudflare 挑战 | 代理隧道已建立;继续测试安装脚本端点 |
| 当前 shell 可联网,重连后失败 | 代理变量没有持久化 | 写入 /etc/profile.d/codex-proxy.sh |
| 容器重建后配置消失 | 修改仅存在于容器可写层 | 将 SSH、Codex 和构建依赖写入 Dockerfile |
11. 持久化到 Docker 镜像
手工安装适合验证,但容器删除后会丢失。稳定使用时建议制作镜像。
示例 Dockerfile:
dockerfile
FROM ubuntu:22.04
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
openssh-server ca-certificates curl git build-essential bubblewrap \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir -p /run/sshd /root/.ssh
RUN printf '%s\n' \
'PubkeyAuthentication yes' \
'PasswordAuthentication no' \
'PermitRootLogin prohibit-password' \
> /etc/ssh/sshd_config.d/99-codex.conf
# 在构建上下文中提供公钥文件,绝不能复制私钥。
COPY docker_wukun.pub /root/.ssh/authorized_keys
RUN chmod 700 /root/.ssh \
&& chmod 600 /root/.ssh/authorized_keys \
&& chown -R root:root /root/.ssh
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D", "-e"]
Codex CLI 安装需要访问官方下载安装地址。可以在构建阶段提供代理,或在基础镜像构建完成后通过受控的网络环境安装。不要把代理凭据、ChatGPT 凭据、API 密钥或 SSH 私钥写入镜像。
12. 安全建议
- SSH 端口绑定
127.0.0.1:2200,不要无必要地绑定0.0.0.0:2200。 - 使用 SSH 密钥并关闭密码登录。
- 长期环境建议创建普通用户,而不是一直使用 root。
- 不要把 SSH 私钥、ChatGPT 凭据或 API 密钥复制进镜像。
- 代理转发尽量仅绑定 WSL 接口,并通过防火墙限制 WSL 子网。
- Codex App Server 不应直接暴露到共享网络或公网;官方建议通过 SSH、VPN或可信网状网络访问。
- 容器重建后若主机指纹变化,先确认目标确实是新容器,再更新
known_hosts。
13. 最短复查清单
text
[ ] ssh docker_wukun 能登录
[ ] 新 SSH 会话能找到 codex
[ ] codex --version 返回版本号
[ ] 新登录 shell 带有正确代理变量
[ ] 容器能下载 Codex 安装脚本
[ ] Codex 已完成身份验证
[ ] 桌面版不再提示 SSH 或 CLI 错误
[ ] 桌面版能打开容器内项目并执行编译命令
本次已完成到"Codex CLI 安装并验证版本"。下一项应是重新连接 Codex 桌面版,并执行第 9 节的端到端验收。