ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Docker 创建深度学习环境并 VSCode Codex 远程使用:TaoToken 统一 Key 配置骨架

Docker 创建深度学习环境并 VSCode Codex 远程使用:TaoToken 统一 Key 配置骨架 1. 为什么要在 Docker 里跑深度学习环境再用 VSCode Codex 远程写代码如果你手头有一台带 GPU 的服务器或者本地机器装了显卡但不想把系统环境搞乱把深度学习环境塞进 Docker 容器、再用 VSCode 远程连进去写代码是目前比较省心的做法。核心逻辑很简单宿主机只负责显卡驱动和 Docker 引擎容器里装 Ubuntu、CUDA、cuDNN、Python、PyTorch 和项目依赖。这样环境可复制、可迁移换机器时把 Dockerfile 和 compose 文件带走就行。但真正落地时会遇到几个具体问题容器里的 Python 解释器怎么让 VSCode 认到、Codex 插件怎么在容器环境里调用模型、API Key 怎么统一管理而不是散落在各个配置文件里。这篇就围绕「Docker 创建深度学习环境 VSCode 远程连接 Codex 插件接入 TaoToken 统一 Key」这条链路给出可以直接复制的 Dockerfile、docker-compose.yml、devcontainer.json 和 Codex settings.json 配置并附上容器内 curl 验证和远程补全测试的完整动作。适合谁看手里有 GPU 机器、想用容器隔离深度学习环境、同时希望用 Codex 做代码补全和辅助开发的开发者。不需要你已经是 Docker 老手但需要你能在终端里执行命令、能编辑配置文件。2. TaoToken 前置准备统一 Key 与 API 通道在讲 Docker 和 VSCode 配置之前先把模型调用这条线理清楚。Codex 插件在容器里运行时需要访问一个兼容 OpenAI 接口的 API 通道。TaoToken 提供的就是这个统一入口你拿到一个 Key配置好 base_urlCodex 就能通过它调用模型。你需要提前做两件事第一注册并获取 API Key。访问 TaoToken 官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 完成注册然后在控制台里创建一个 API Key。这个 Key 后面会写进 Codex 的配置文件里。第二确认 API 通道地址。TaoToken 的 API 端点是 https://taotoken.net/api这个地址不加 UTM 参数直接作为 base_url 使用。Codex 插件和 CLI 都支持自定义 base_url所以你可以把请求指向这个通道。注意API Key 不要写进 Dockerfile也不要用ENV指令固化到镜像里。镜像层是可以被导出的Key 泄露风险很高。正确做法是通过环境变量注入或者放在宿主机的.env文件里由 docker-compose 读取后传给容器。如果你还没创建 Key可以先打开 API Keys 管理页面https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。创建后复制保存后面配置 Codex 时直接粘贴。3. Dockerfile 与 docker-compose 骨架容器内深度学习环境3.1 基础镜像选择不要用裸的ubuntu:22.04从头装 CUDA直接用 NVIDIA 官方带 CUDA 和 cuDNN 的镜像。推荐FROM nvidia/cuda:12.8.1-cudnn-devel-ubuntu22.04这个镜像本质是 Ubuntu 22.04但已经带好了 CUDA 12.8 和 cuDNN 开发环境适合 PyTorch、CUDA 扩展编译、YOLO、OpenCV 等场景。如果你的宿主机nvidia-smi显示的 CUDA Version 低于 12.8就把基础镜像和 PyTorch 安装源都降到 cu126。3.2 Dockerfile 完整骨架在项目目录dl-docker/Dockerfile写入FROM nvidia/cuda:12.8.1-cudnn-devel-ubuntu22.04 ARG USERNAMEdev ARG USER_UID1000 ARG USER_GID1000 ARG PYTHON_VERSION3.11 ENV DEBIAN_FRONTENDnoninteractive ENV TZAsia/Shanghai ENV CONDA_DIR/opt/conda ENV PATH/opt/conda/bin:$PATH ENV PIP_CACHE_DIR/cache/pip ENV HF_HOME/cache/huggingface ENV TRANSFORMERS_CACHE/cache/huggingface ENV TORCH_HOME/cache/torch ENV PYTHONUNBUFFERED1 ENV PYTHONDONTWRITEBYTECODE1 RUN apt-get update apt-get install -y --no-install-recommends \ sudo git git-lfs wget curl vim nano tmux htop tree unzip zip \ ca-certificates build-essential cmake ninja-build pkg-config \ ffmpeg libgl1 libglib2.0-0 libsm6 libxext6 libxrender-dev libgomp1 \ openssh-client nodejs npm \ rm -rf /var/lib/apt/lists/* RUN groupadd --gid ${USER_GID} ${USERNAME} \ useradd --uid ${USER_UID} --gid ${USER_GID} -m ${USERNAME} -s /bin/bash \ echo ${USERNAME} ALL(ALL) NOPASSWD:ALL /etc/sudoers.d/${USERNAME} \ chmod 0440 /etc/sudoers.d/${USERNAME} RUN wget -q https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /tmp/miniconda.sh \ bash /tmp/miniconda.sh -b -p ${CONDA_DIR} \ rm /tmp/miniconda.sh \ ${CONDA_DIR}/bin/conda clean -afy RUN conda create -y -n dl python${PYTHON_VERSION} \ conda clean -afy SHELL [conda, run, -n, dl, /bin/bash, -c] RUN pip install --upgrade pip setuptools wheel \ pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128 COPY requirements.txt /tmp/requirements.txt RUN pip install -r /tmp/requirements.txt \ rm /tmp/requirements.txt RUN npm install -g openai/codex || true RUN echo source /opt/conda/etc/profile.d/conda.sh /home/${USERNAME}/.bashrc \ echo conda activate dl /home/${USERNAME}/.bashrc \ echo cd /workspace /home/${USERNAME}/.bashrc RUN mkdir -p /workspace /data /outputs /cache \ chown -R ${USERNAME}:${USERNAME} /workspace /data /outputs /cache /home/${USERNAME} USER ${USERNAME} WORKDIR /workspace CMD [/bin/bash]关键点说明创建了非 root 用户dev避免 VSCode 和 Codex 写出的文件在宿主机上变成 root 权限conda 环境命名为dlPython 3.11PyTorch 用 cu128 源安装Codex CLI 通过 npm 全局安装容器终端里可以直接用。3.3 requirements.txtnumpy pandas scipy scikit-learn matplotlib seaborn opencv-python pillow tqdm rich jupyterlab notebook ipywidgets tensorboard wandb mlflow einops timm albumentations ultralytics transformers datasets accelerate peft sentencepiece protobuf safetensors huggingface_hub openpyxl pyyaml python-dotenv pytest black isort ruff mypy做 CV 就保留 ultralytics、opencv-python、albumentations做大模型就重点保留 transformers、datasets、accelerate、peft。3.4 docker-compose.ymlservices: dl-ubuntu: build: context: . dockerfile: Dockerfile args: USERNAME: dev USER_UID: 1000 USER_GID: 1000 PYTHON_VERSION: 3.11 image: dl-ubuntu-cuda128:latest container_name: dl-ubuntu runtime: nvidia environment: NVIDIA_VISIBLE_DEVICES: all NVIDIA_DRIVER_CAPABILITIES: compute,utility PYTHONUNBUFFERED: 1 HF_HOME: /cache/huggingface TRANSFORMERS_CACHE: /cache/huggingface TORCH_HOME: /cache/torch PIP_CACHE_DIR: /cache/pip TZ: Asia/Shanghai volumes: - ./workspace:/workspace - ./data:/data - ./outputs:/outputs - ./cache:/cache ports: - 8810:8888 - 6116:6006 - 5010:5000 - 7870:7860 - 8010:8000 shm_size: 16gb ipc: host stdin_open: true tty: true command: /bin/bashshm_size和ipc: host对多 GPU 训练和 PyTorch DataLoader 很重要能减少共享内存不足的报错。如果你的宿主机 UID/GID 不是 1000先用id -u和id -g查一下把 compose 里的值改掉。4. VSCode 远程连接与 Codex 插件配置4.1 连接路径整体路径是本地 VSCode → Remote-SSH 连到 GPU 服务器 → 在服务器上 Attach 到运行中的容器 → 在容器/workspace里写代码、跑训练、用 Codex。本地 VSCode 需要装这些扩展Remote - SSH、Dev Containers、Docker、Python、Jupyter、Codex。先Ctrl Shift P执行Remote-SSH: Connect to Host...输入ssh 用户名服务器IP连接成功后左下角显示SSH: 服务器IP。然后继续Ctrl Shift P执行Dev Containers: Attach to Running Container...选择dl-ubuntu容器。VSCode 会重新打开一个窗口左下角显示Dev Container: dl-ubuntu这时你已经进入容器环境。打开/workspace目录即可开始工作。4.2 devcontainer.json在dl-docker/.devcontainer/devcontainer.json写入{ name: dl-ubuntu-cuda, dockerComposeFile: ../docker-compose.yml, service: dl-ubuntu, workspaceFolder: /workspace, shutdownAction: none, remoteUser: dev, customizations: { vscode: { settings: { terminal.integrated.defaultProfile.linux: bash, python.defaultInterpreterPath: /opt/conda/envs/dl/bin/python, python.terminal.activateEnvironment: true, files.autoSave: afterDelay, editor.formatOnSave: true }, extensions: [ ms-python.python, ms-python.vscode-pylance, ms-toolsai.jupyter, ms-azuretools.vscode-docker, ms-vscode-remote.remote-containers, openai.chatgpt ] } }, postAttachCommand: python -V nvidia-smi || true }4.3 Codex 插件接入 TaoToken 统一 KeyCodex 插件在 VSCode 里运行时读取的是用户级或项目级配置文件。用户级配置在~/.codex/config.toml项目级配置在/workspace/.codex/config.toml。CLI 和 IDE 扩展共享配置层。在容器内创建配置文件mkdir -p ~/.codex cat ~/.codex/config.toml EOF model gpt-5.5 approval_policy on-request sandbox_mode workspace-write [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chat EOF然后在容器用户环境里注入 Key。不要写死在配置文件里用环境变量echo export TAOTOKEN_API_KEY你的Key ~/.bashrc source ~/.bashrc如果你用的是 VSCode 的 Codex 插件面板它启动的是 extension host 进程不一定继承你当前 bash 终端的环境变量。所以更稳的做法是在devcontainer.json的remoteEnv里注入或者在 docker-compose 的environment段里通过.env文件传入。在 docker-compose.yml 同级目录创建.envTAOTOKEN_API_KEY你的Key然后在 compose 的environment段加一行TAOTOKEN_API_KEY: ${TAOTOKEN_API_KEY}这样容器启动时环境变量就已经存在Codex 插件进程也能读到。5. 验证请求与远程补全测试5.1 容器内 curl 验证进入容器docker exec -it dl-ubuntu bash先确认环境变量env | grep TAOTOKEN然后用 curl 测试 API 通道curl -s -o /dev/null -w %{http_code}\n \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ https://taotoken.net/api/v1/models如果返回200说明 Key 和通道都正常。返回401说明 Key 没带上或无效返回404检查 base_url 路径。5.2 GPU 与 PyTorch 验证python - PY import torch print(torch:, torch.__version__) print(cuda available:, torch.cuda.is_available()) print(cuda version:, torch.version.cuda) print(gpu count:, torch.cuda.device_count()) if torch.cuda.is_available(): print(gpu name:, torch.cuda.get_device_name(0)) x torch.randn(2048, 2048, devicecuda) y x x print(matmul ok:, y.mean().item()) PY看到cuda available: True和矩阵乘法结果说明容器 GPU 环境没问题。5.3 Codex 远程补全测试在 VSCode 容器窗口里打开/workspace下的一个 Python 文件写几行代码触发 Codex 补全。如果补全正常返回说明插件已经通过 TaoToken 通道调到了模型。你也可以在容器终端里直接用 Codex CLI 测试codex 写一个 PyTorch DataLoader 的例子如果 CLI 能返回结果但 VSCode 插件面板不行问题通常出在插件进程没有继承环境变量。这时候执行Developer: Reload Window重启扩展宿主或者Dev Containers: Reopen in Container重新进入容器。6. 本篇常见错误排查6.1 Codex 插件报 401 或连接超时最常见的原因是插件进程没有拿到TAOTOKEN_API_KEY环境变量。你只在当前终端export是不够的VSCode 的 extension host 是独立进程。解决办法是把 Key 写进 docker-compose 的environment段或者写进devcontainer.json的remoteEnv然后重启容器和 VSCode 窗口。6.2 PyTorch 报 CUDA 不可用先在宿主机执行nvidia-smi确认驱动正常再在容器里执行nvidia-smi。如果宿主机有、容器没有检查 docker-compose 里runtime: nvidia和NVIDIA_VISIBLE_DEVICES是否配置正确。另外确认没有在容器里装 NVIDIA 驱动驱动属于宿主机容器只需要 CUDA runtime 和 PyTorch 的 CUDA wheel。6.3 OpenCV 报 libGL.so.1 找不到Dockerfile 里已经装了libgl1和libglib2.0-0。如果还是报错检查是不是在 conda 环境外运行的 Python或者 pip 装的 opencv 版本和系统库不匹配。可以在容器里执行ldd $(python -c import cv2; print(cv2.__file__)) | grep not found看具体缺哪个库。6.4 DataLoader 报 shared memory 不足把 docker-compose 里的shm_size调大比如16gb同时保留ipc: host。这两个配置对多进程数据加载和 NCCL 通信都有帮助。6.5 VSCode 反复重连或容器内终端环境不对如果你是通过 Remote-SSH 先连服务器再 Attach 容器确认devcontainer.json里的remoteUser是dev而不是 root。另外shutdownAction: none可以避免 VSCode 断开时容器被停掉。如果终端里 conda 环境没自动激活检查.bashrc里的conda activate dl是否写进去了。6.6 API 请求返回 404检查 base_url 是否写成了https://taotoken.net/api不要多加/v1或末尾斜杠。Codex 的wire_api设为chat时它会自动拼接路径。如果返回 404先用 curl 直接测https://taotoken.net/api/v1/models确认通道可达。7. 后续维护与扩展这套配置跑通之后你真正需要维护的核心文件就四个Dockerfile、requirements.txt、docker-compose.yml、.devcontainer/devcontainer.json。环境变更写进 Dockerfile依赖变更写进 requirements.txt容器编排变更写进 composeVSCode 和 Codex 的接入配置写进 devcontainer.json 和 config.toml。如果你后续要做长期编码或 Agent 类任务可以了解 TaoToken 的 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。如果只是想验证模型对话效果可以直接用模型对话页面https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 控制台在 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。数据集不要复制进镜像用 volume 挂到/data。模型缓存挂到/cache/huggingface避免每次重建容器重新下载。环境变更不要用docker commit写进 Dockerfile 才能被 Codex 识别和修改。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进