DevContainers
使用 Dev Containers 进行 Python 开发
VSCode 的远程开发非常方便,可以在桌面上直接借用远程服务器的环境进行开发。不过,与在本地开发一样,开发的项目多了,也会让环境很混乱,所以还是需要一个容器开发环境。
Dev Container 的默认配置支持的是 Docker 的 Daemon 在本地的情况,但我希望连接到我的某个服务器上,用这个服务器的容器开发。一方面我真的不太想在本机启动 Docker 服务,占用太多的资源;其次,我的服务器是 Linux 的,也可能存放在任何地方,这样我可以做许多我本机做起来不方便的事情。
为了实现这个目标,VSCode 提供了两个选项:
- A:本机的 VSCode 配置 SSH Remote 插件,实现远程开发,然后在远程开发环境的主机实现 Dev Container 开发。
- B: 在本机配置好 Docker 客户端到远程 Docker Daemon 的关联,然后直接在本机配置 Dev Container 开发。
其实 B 方案中 Docker 客户端到远程 Docker Daemon 也是通过的 SSH 连接,不过从 VSCode 的角度,感官上和默认用法更相似,我觉得更自然一点,本文采用这个模式。
前置条件
我的远程服务器已经有了账号,这个账号可以通过 SSH 访问。而且这个账号有了 Docker 权限,可以执行 docker 命令。
配置使用 SSH 密钥访问远程服务器
Windows 10 已经内置了 ssh 的一些工具,这一步可以像其他 Linux 一样操作,在 Powershell 下:
ssh-keygen -t rsa -b 4096 -C "[email protected]"这一步会生成证书。下一步,如果没有 ,可以用下面的 Powershell 命令:
# 读取公钥并通过 SSH 添加到远程主机
$publicKey = Get-Content "$env:USERPROFILE\.ssh\id_rsa.pub"
ssh user@remote_host "mkdir -p ~/.ssh && echo '$publicKey' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys && chmod 700 ~/.ssh"然后我们测试 ssh 连接:
ssh user@remote_host如果直接进入远程主机的 shell 界面,说明配置成功。
配置 Docker Context
虽然我用的 windows,但我也需要一些常用的 Linux 命令,包括 ssh 等。大家都有自己的安装方法,我用的是 scoop,也推荐大家使用 scoop 管理 Windows 上的常用工具,大多数情况下,一个 scoop install xxx 还是比网上下载安装方便多了。
这一步需要一个 docker client,我直接运行:
scoop install docker不过这只是个 docker 命令行,本地没有 docker daemon,所以并不能管理容器。下一步就需要建立本地 docker 和远程服务器的关联。执行以下命令:
docker context create remote-dev --docker "host=ssh://user@remote-host"
docker context use remote-dev如果一切正常执行 docker info 应该可以显示远程服务器的 docker 信息了。
配置 devcontainer.json
我们创建一个项目,只有两个文件,首先是 .devcontainer\devcontainer.json :
{
"name": "Python 3.12 Dev Container",
"image": "mcr.microsoft.com/devcontainers/python:3.12",
"customizations": {
"vscode": {
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python"
},
"extensions": [
"ms-python.python",
"streetsidesoftware.code-spell-checker"
]
}
},
"workspaceFolder": "/workspace",
"workspaceMount": "source=remote-workspace,target=/workspace,type=volume"
}其中的 workspaceFolder 和 workspaceMount 很关键,设置了远程工作目录,以及存储工作目录的 docker volume。
然后项目中有一个 hello.py :
print("Hello world!")然后我们按 Ctrl+Shift+P,然后选择 Dev Containers: Reopen in Container,静待一会儿,新开了一个远程窗口,这个就应该是容器中的 VSCode 了。
不过,你会发现项目里并没有 hello.py,这就是远程 Docker 服务和本地 Docker 服务的区别了,本地会共享项目目录,而远程这个并没有共享。
此时,你可以选择使用 git 获取你的项目,项目文件会存放到 remote-workspace 卷中。Dev Container 也会将你本地的 git 信息同步到容器中,这样无需在容器里重复配置 git 了。
不过这又带来了新的问题,为了正常访问 github ,配置了代理,而在我的远程服务器上代理并不一样,此时,可以在 devcontainer.json 中配置一个 postStartCommand:
"postStartCommand": "git config --global http.https://github.com.proxy socks5://192.168.0.107:20170 && git config --global https.https://github.com.proxy socks5://192.168.0.107:20170",配置代理
后来我发现,还是需要给 VSCode 的其他插件配置代理,可以在 devcontainer.json 中增加:
"remoteEnv": {
"HTTP_PROXY": "http://192.168.0.107:21171",
"HTTPS_PROXY": "http://192.168.0.107:21171",
"NO_PROXY": "localhost,127.0.0.1,192.168.0.107,main.vscode-cdn.net,www.timescale.com,reddit.com,appetals.com,thenewstack.io,.amazonaws.com,update.code.visualstudio.com,*.eks.amazonaws.com,vscode.download.prss.microsoft.com,*.visualstudio.com,vscode.blob.core.windows.net,*.visualstudio.com,*.data.microsoft.com"
}扩展容器环境
我的 Python 应用需要调用 ffmpeg ,所以要扩展容器。
本来希望通过 devcontainer.json 的 features 实现,不过在我的环境里执行报错,所以我还是构建自己的镜像实现,所以编写了以下 Dockerfile:
ARG UV_VERSION=latest
FROM ghcr.io/astral-sh/uv:$UV_VERSION AS uv
FROM mcr.microsoft.com/devcontainers/python:3.12
LABEL maintainer="rocksun <[email protected]>"
# hadolint ignore=DL3008
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
# For ffmpeg etc...
ffmpeg \
# To remove the image size, it is recommended refresh the package cache as follows
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
COPY --from=uv --chown=vscode: /uv /uvx /bin/除了 ffmpeg,还增加了 uv 。
然后修改我的 devcontainer.json :
"image": "rocksun/subt-env:1.0",重新运行 Dev Container 即可。
总结
devcontainer.json 中还有许多配置选项,可以参考官方文档。