devcontainer.json 必须置于 .devcontainer/ 目录下,否则 GitHub Codespaces 不识别;需明确指定 image 或 features、声明 forwardPorts 和启动命令,并通过 postCreateCommand 复制 .env.devcontainer 到容器内。

devcontainer.json 必须放在 .devcontainer/ 目录下
GitHub Codespaces 只识别 .devcontainer/devcontainer.json 这个路径的配置文件,放错位置(比如根目录、.vscode/ 或 devcontainer.json 没加点)会导致配置完全不生效,codespace 会退回到默认环境。
常见错误现象包括:
- 终端里
python --version显示的是系统自带的旧版本,而非你指定的版本 -
pip list里看不到你声明要预装的包(如fastapi、psycopg2) - VS Code 命令面板搜不到 “Dev Containers: Rebuild Container” 选项
正确做法是:在仓库根目录新建 .devcontainer 文件夹,再把 devcontainer.json 放进去。用 VS Code 打开时,它会自动提示“检测到开发容器配置”,点击“重新生成容器”即可生效。
基础配置要明确指定 image 或 features
不要依赖默认容器——它虽然带 Python,但版本固定(当前是 3.11)、没数据库驱动、没 uvicorn、没 lint 工具。想稳定复现环境,必须显式控制运行时。
立即学习“Python免费学习笔记(深入)”;
两种主流写法:
- 用
"image": "mcr.microsoft.com/devcontainers/python:3.12"拉官方镜像(推荐,启动快、兼容性好) - 用
"features"声明扩展能力,例如:{ "features": { "ghcr.io/devcontainers/features/postgresql:1": {}, "ghcr.io/devcontainers/features/python:1": { "version": "3.12" } } }这种方式更轻量,适合组合 PostgreSQL + Python + Node.js 等多服务场景
注意:features 的版本号必须带冒号(如 :1),漏掉会报 Feature not found 错误;image 方式则无法直接启用 PostgreSQL 服务,得额外配 docker-compose.yml。
启动命令和端口转发必须手动声明
Codespaces 不会自动识别你的 Web 服务端口或执行启动脚本。FastAPI 用 uvicorn main:app --reload、Flask 用 flask run,这些都得写进 "postStartCommand" 或 "customizations.vscode.launch" 里,否则容器起来后服务根本没跑。
同时,端口必须显式转发,否则浏览器打不开:
- 在
devcontainer.json中加:"forwardPorts": [8000, 5432]
- 如果用
docker-compose.yml启 Postgres,确保它有ports: ["5432:5432"] - 访问时用
https://<your-codespace-url>-8000.githubpreview.dev</your-codespace-url>,不是 localhost
漏掉 forwardPorts 是最常被忽略的点——终端显示 Uvicorn running on http://0.0.0.0:8000,但点链接 404,就是这个原因。
环境变量和 .env 文件要复制到容器内
本地开发常用的 .env(含 DATABASE_URL、SECRET_KEY)不会自动进容器。Codespaces 默认只挂载仓库代码,不加载根目录下的隐藏文件。
解决方法只有两个:
- 在
devcontainer.json的"postCreateCommand"里加:cp .env.devcontainer .env
(前提是先提交一个.env.devcontainer作为模板) - 用
"remoteEnv"注入单个变量,例如:"remoteEnv": { "PYTHONUNBUFFERED": "1" }
别试图用 ENV 写进 Dockerfile——devcontainer.json 优先级更高,且多数人用的是 image 模式,没 Dockerfile。另外,.env 文件本身不该提交到 Git,所以必须用 .env.devcontainer 作占位,再靠脚本复制。
真正麻烦的从来不是写几行 JSON,而是每个字段的生效边界:路径错一位、端口少写一个、.env 漏复制,都会让“一键环境”变成手动救火。建议每次改完 devcontainer.json 都执行一次 Dev Containers: Rebuild Container,别指望热重载。


















