在 Windows 上做 Python 容器化开发,最省心的路线是采用一套清晰的分工:
- Windows 负责桌面应用、浏览器、Docker Desktop
- WSL 2 负责 Git、Python、Shell 和项目文件
- Docker 容器 负责统一运行环境
- VS Code 通过 WSL 或 Dev Containers 进入开发环境
一句话概括就是,代码放进 WSL,编辑器连进 WSL,Docker Desktop 接管容器,最终交付 Linux 镜像。这样可以显著减少路径、权限、换行符和依赖编译方面的麻烦。
一、推荐的整体架构
下面这套结构兼顾开发体验和交付一致性。

这里有一个很关键的原则:
不要把高频开发的代码放在
C:\Users\...,再从 WSL 或 Linux 容器中反复读取。
更推荐放在 WSL 的 Linux 文件系统中,例如:
bash
~/projects/my-python-app
也就是:
text
/home/你的用户名/projects/my-python-app
WSL 2 和 Docker Desktop 能够直接协作。项目放在 Linux 文件系统后,文件监听、依赖安装、Git 操作以及容器挂载通常都会更快,也更接近最终的 Linux 生产环境。,
二、一次性完成基础环境配置
环境只需要认真配置一次,后面基本就是开机、打开项目、开始写代码。
1. 安装并更新 WSL 2
以管理员身份打开 PowerShell,执行:
powershell
wsl --install -d Ubuntu
安装结束后重启 Windows,再检查发行版状态:
powershell
wsl --list --verbose
正常情况下会看到类似结果:
text
NAME STATE VERSION
Ubuntu Running 2
如果不是 WSL 2,可以执行:
powershell
wsl --set-version Ubuntu 2
wsl --set-default-version 2
更新 WSL:
powershell
wsl --update
进入 Ubuntu:
powershell
wsl
随后更新基础软件:
bash
sudo apt update
sudo apt upgrade -y
sudo apt install -y git curl build-essential
Docker Desktop 官方建议使用较新的 WSL 版本,并启用 WSL 2 后端,以获得更完整的文件系统、网络和容器功能支持。,
2. 安装 Docker Desktop
安装 Docker Desktop for Windows 后,打开设置页面:
text
Settings
└── General
└── Use the WSL 2 based engine
然后进入:
text
Settings
└── Resources
└── WSL Integration
└── Enable integration with Ubuntu
保存并重启 Docker Desktop。
回到 Ubuntu 中验证:
bash
docker version
docker compose version
docker run --rm hello-world
这些命令能正常运行,说明 WSL 不需要额外安装一套 Docker Engine。此时,WSL 中的 Docker CLI 会直接连接 Docker Desktop 管理的引擎。
不要同时在 Ubuntu 中用 apt install docker.io 再装一套 Docker,否则容易出现两个守护进程、两个上下文和两套镜像缓存,排查起来颇有一种左右手互搏的美感。,
3. 安装 VS Code 扩展
Windows 侧安装 VS Code,并加入以下扩展:
- WSL
- Dev Containers
- Docker
- Python
- Pylance
进入 WSL 后创建项目目录:
bash
mkdir -p ~/projects
cd ~/projects
mkdir my-python-app
cd my-python-app
code .
执行 code . 后,VS Code 会以 WSL 模式打开。窗口左下角应显示类似:
text
WSL: Ubuntu
此时,VS Code 界面运行在 Windows,终端、Git、Python 扩展和代码分析则运行在 WSL 中,两边分工明确。官方文档也把 WSL 集成和 Dev Containers 作为 Windows 容器开发的推荐工作方式。,
三、选择适合自己的开发模式
Python 容器化开发大致有三种模式。对大多数团队来说,推荐从第二种起步,项目复杂后再切到第三种。
| 模式 | Python 运行位置 | 优势 | 适用场景 |
|---|---|---|---|
| WSL 本地虚拟环境 | WSL | 启动快、调试简单 | 脚本、算法、小型项目 |
| WSL 编码 + Docker 运行 | 容器 | 环境一致、操作直观 | Web 服务、常规团队项目 |
| Dev Containers | 容器 | 编辑器和工具链也统一 | 多人协作、复杂依赖、跨平台团队 |
Dev Containers 可以把 Python、调试器、扩展、系统依赖和项目配置一起声明。新成员克隆代码后直接打开容器,不必照着安装文档逐项"考古"。,
四、一个实用的 Python 项目模板
下面以一个普通 Python 服务为例。项目结构可以这样安排:
text
my-python-app/
├── app/
│ ├── __init__.py
│ └── main.py
├── tests/
│ └── test_main.py
├── .devcontainer/
│ └── devcontainer.json
├── .dockerignore
├── .gitignore
├── compose.yaml
├── Dockerfile
├── requirements.txt
└── README.md
1. 示例程序
app/main.py:
python
def main() -> None:
print("Hello from Python and Docker")
if __name__ == "__main__":
main()
requirements.txt:
text
pytest==8.3.5
实际项目中更推荐使用明确版本或锁文件,避免今天构建和下个月构建得到不同的依赖组合。
2. 编写生产友好的 Dockerfile
dockerfile
# syntax=docker/dockerfile:1
FROM python:3.12-slim AS builder
ENV PIP_DISABLE_PIP_VERSION_CHECK=1 \
PIP_NO_CACHE_DIR=1
WORKDIR /build
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
COPY requirements.txt ./
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
FROM python:3.12-slim AS runtime
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PATH="/opt/venv/bin:$PATH"
WORKDIR /workspace
COPY --from=builder /opt/venv /opt/venv
COPY app ./app
RUN useradd --create-home --uid 10001 appuser \
&& chown -R appuser:appuser /workspace
USER appuser
CMD ["python", "-m", "app.main"]
这份 Dockerfile 做了几件实用的事:
- 使用
python:3.12-slim,减少镜像体积 - 先复制依赖文件,再复制源码,充分利用构建缓存
- 使用多阶段构建,不把编译过程中的杂物带入运行镜像
- 设置
PYTHONUNBUFFERED=1,让日志及时输出 - 生产环境使用普通用户运行,而不是默认的 root
- 使用 exec 格式的
CMD,便于容器正确接收终止信号
如果依赖中包含 psycopg、numpy、Pillow 等需要系统库的软件包,可以只在 builder 阶段安装编译工具,在 runtime 阶段保留必要的动态链接库。这样既能成功编译,也不会把整套编译环境塞进最终镜像。
3. 配置 .dockerignore
dockerignore
.git
.github
.vscode
.devcontainer
.venv
venv
__pycache__
*.py[cod]
.pytest_cache
.mypy_cache
.ruff_cache
.coverage
htmlcov
dist
build
*.egg-info
.env
.env.*
tests
README.md
.dockerignore 可以减少发送给 Docker 的构建上下文,让构建速度更快,也能防止 .env、Git 历史和本地虚拟环境被误装进镜像。,
五、用 Compose 打通开发流程
compose.yaml:
yaml
services:
app:
build:
context: .
dockerfile: Dockerfile
working_dir: /workspace
volumes:
- .:/workspace
command: python -m app.main
environment:
PYTHONUNBUFFERED: "1"
在项目目录运行:
bash
docker compose up --build
停止服务:
bash
docker compose down
重新构建:
bash
docker compose build
后台运行:
bash
docker compose up -d
查看日志:
bash
docker compose logs -f app
进入容器:
bash
docker compose exec app bash
运行测试:
bash
docker compose run --rm app pytest
这里把项目目录挂载到 /workspace,修改代码后容器能立即看到变化。由于项目本身位于 WSL 的 Linux 文件系统中,这种 bind mount 通常比挂载 C:\... 下的项目更稳定、响应更快。,
六、进一步升级为 Dev Containers
当团队希望连 VS Code 扩展、解释器和终端环境都完全一致时,可以加入 .devcontainer/devcontainer.json:
json
{
"name": "Python Docker Development",
"dockerComposeFile": "../compose.yaml",
"service": "app",
"workspaceFolder": "/workspace",
"overrideCommand": true,
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"charliermarsh.ruff",
"ms-azuretools.vscode-docker"
],
"settings": {
"python.defaultInterpreterPath": "/opt/venv/bin/python",
"python.testing.pytestEnabled": true,
"python.testing.unittestEnabled": false,
"editor.formatOnSave": true
}
}
},
"postCreateCommand": "python --version && pip --version"
}
在 VS Code 命令面板中执行:
text
Dev Containers: Reopen in Container
重新打开后:
- VS Code 终端位于容器内
- Python 解释器使用
/opt/venv/bin/python - 调试和测试都在容器环境执行
- 团队成员使用同一组扩展和配置
- Windows 本机不必单独安装项目所需的 Python 版本
Dev Containers 的核心价值不是"把代码关进容器",而是把开发环境本身变成可版本管理的配置。这对于新成员入职、CI 故障复现和多项目切换尤其有帮助。, ,
七、本地开发与生产镜像要适当分开
开发环境追求热更新、调试便利和源码挂载,生产镜像追求小体积、安全和可重复部署。两者可以共享 Dockerfile,但运行方式不要完全混在一起。
开发阶段
bash
docker compose up --build
特点包括:
- 挂载源码
- 开放调试端口
- 安装测试工具
- 允许热更新
- 日志直接输出到终端
交付阶段
构建镜像:
bash
docker build -t my-python-app:1.0.0 .
运行验证:
bash
docker run --rm my-python-app:1.0.0
查看镜像:
bash
docker image ls my-python-app
检查镜像历史:
bash
docker history my-python-app:1.0.0
生产镜像中不要挂载本地源码,也不要把 .env 文件复制进去。数据库密码、令牌和证书应在部署阶段通过环境变量、Docker secrets 或云平台的密钥管理服务注入。
开发和生产共享同一套基础定义,但保留必要差异,往往比强行追求"一份配置统治所有环境"更可靠。,
八、Windows 环境最常见的几个坑
1. 项目放在 Windows 盘中
不推荐:
bash
cd /mnt/c/Users/your-name/project
更推荐:
bash
cd ~/projects/project
在 Windows 资源管理器中需要访问 WSL 文件时,可以输入:
text
\\wsl$\Ubuntu\home\你的用户名\projects
日常编辑仍建议从 WSL 中执行 code .,不要频繁通过 Windows 文件系统工具批量操作 Linux 项目文件。,
2. Git 换行符变成 CRLF
Linux 容器通常期望 LF。可以在 WSL 中设置:
bash
git config --global core.autocrlf input
项目根目录加入 .gitattributes:
gitattributes
* text=auto eol=lf
*.bat text eol=crlf
*.cmd text eol=crlf
*.ps1 text eol=crlf
否则 Shell 脚本进入容器后,可能出现这种颇具迷惑性的错误:
text
/bin/sh^M: bad interpreter
3. Windows 和 WSL 各装一套 Git
代码放在 WSL 后,应优先使用 WSL 中的 Git:
bash
which git
git --version
SSH 密钥也放在:
text
~/.ssh/
设置权限:
bash
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
测试 GitHub 连接:
bash
ssh -T git@github.com
这样能避免 Windows Git、WSL Git、不同凭据管理器之间互相"猜心思"。
4. 容器里写出的文件归 root
开发容器以 root 运行时,可能在挂载目录中生成 root 所有的文件。可采用以下办法:
- 在镜像中创建普通用户
- Dev Container 中配置
remoteUser - 让容器用户 UID 与 WSL 用户 UID 对齐
- 避免容器向源码目录写入缓存和构建产物
查看 WSL 用户 UID:
bash
id -u
id -g
团队项目可以通过 Dockerfile 的构建参数传入 UID 和 GID,不过 Windows + Docker Desktop 场景通常没有原生 Linux 那么容易出现严重权限冲突。
5. 修改代码后镜像仍是旧版本
如果 Dockerfile 先执行:
dockerfile
COPY . .
RUN pip install -r requirements.txt
那么任何代码变更都会让依赖安装层失效。正确顺序应当是:
dockerfile
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY app ./app
缓存利用率的差别相当明显,尤其是科学计算和机器学习依赖较多时。
6. 容器访问宿主机服务失败
容器中的 localhost 指向容器自己,不是 Windows。
从容器访问 Windows 宿主机上的服务,可以尝试:
text
host.docker.internal
例如 Windows 上的服务监听 8000 端口:
text
http://host.docker.internal:8000
容器之间则应通过 Compose 服务名通信。例如数据库服务名为 db,应用应连接:
text
postgresql://user:password@db:5432/database
而不是连接 localhost。
九、推荐的日常工作流
一套稳定的操作节奏可以压缩成下面几步。
bash
# 从 Windows Terminal 进入 WSL
wsl
# 进入项目
cd ~/projects/my-python-app
# 拉取代码
git pull
# 用 WSL 模式打开 VS Code
code .
# 启动开发容器
docker compose up --build
# 运行测试
docker compose run --rm app pytest
# 构建交付镜像
docker build -t my-python-app:$(git rev-parse --short HEAD) .
# 验证交付镜像
docker run --rm my-python-app:$(git rev-parse --short HEAD)
如果采用 Dev Containers,打开项目后执行 Reopen in Container,Python 解释器、测试工具和调试环境都会跟随项目自动加载。
最终可以记住这套组合:
WSL 文件系统存代码,VS Code Remote WSL 做编辑,Docker Compose 做开发编排,Dockerfile 做正式交付,Dev Containers 做团队环境统一。
它不会消灭所有环境问题------软件工程还没幸福到那个程度------但能把 Windows、Linux 和容器之间最常见的摩擦压到很低。, ,
参考资料
-
Docker Documentation, Docker Desktop WSL 2 backend on Windows
-
Docker Documentation, WSL 2 best practices for Docker Desktop on Windows
-
Docker Documentation, Install Docker Desktop on Windows
-
Docker Documentation, Develop with Docker Desktop using WSL 2
-
Visual Studio Code Documentation, Developing inside a Container
-
Visual Studio Code Documentation, Create a Dev Container
-
Visual Studio Code Documentation, Dev Container metadata reference