dev container是干啥用的呢?我理解dev container是构建一个通用的开发环境,比如c语言,不同平台有不同的编译工具链,我在windows上下载了一份python源代码,怎么编译呢?dev container给出了一个解决方案,基于docker容器技术,dev container可以构建一致的开发环境,比如我编写好了一份dockerfile,该dockerfile构建了我的编译环境,dev container把dockerfile和编译命令连接在了一起,在vscode中使用dev container可以自动构建编译环境(即那个docker容器),并执行编译命令,python3的源码中就是这样做的。
让我们看一下python3.13.2版本的源码中的devcontainer.json和Dockerfile:
FROM docker.io/library/fedora:40
ENV CC=clang
ENV WASI_SDK_VERSION=24
ENV WASI_SDK_PATH=/opt/wasi-sdk
ENV WASMTIME_HOME=/opt/wasmtime
ENV WASMTIME_VERSION=22.0.0
ENV WASMTIME_CPU_ARCH=x86_64
RUN dnf -y --nodocs --setopt=install_weak_deps=False install /usr/bin/{blurb,clang,curl,git,ln,tar,xz} 'dnf-command(builddep)' && \
dnf -y --nodocs --setopt=install_weak_deps=False builddep python3 && \
dnf -y clean all
RUN mkdir ${WASI_SDK_PATH} && \
curl --location https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/wasi-sdk-${WASI_SDK_VERSION}.0-x86_64-linux.tar.gz | \
tar --strip-components 1 --directory ${WASI_SDK_PATH} --extract --gunzip
RUN mkdir --parents ${WASMTIME_HOME} && \
curl --location "https://github.com/bytecodealliance/wasmtime/releases/download/v${WASMTIME_VERSION}/wasmtime-v${WASMTIME_VERSION}-${WASMTIME_CPU_ARCH}-linux.tar.xz" | \
xz --decompress | \
tar --strip-components 1 --directory ${WASMTIME_HOME} -x && \
ln -s ${WASMTIME_HOME}/wasmtime /usr/local/bin
以上dockerfile基于fedora镜像构建,安装了WASI_SDK和WASMTIME,和一些编译所需的包,可以理解这就是我们的编译环境了。
那么devcontainer.json呢?
{
"build": {
"dockerfile": "Dockerfile"
},
"onCreateCommand": [
// Install common tooling.
"dnf",
"install",
"-y",
"which",
"zsh",
"fish",
// For umask fix below.
"/usr/bin/setfacl"
],
"updateContentCommand": {
// Using the shell for `nproc` usage.
"python": "./configure --config-cache --with-pydebug && make -s -j `nproc`",
"docs": [
"make",
"--directory",
"Doc",
"venv",
"html"
]
},
"postCreateCommand": {
// https://github.com/orgs/community/discussions/26026
"umask fix: workspace": ["sudo", "setfacl", "-bnR", "."],
"umask fix: /tmp": ["sudo", "setfacl", "-bnR", "/tmp"]
},
"customizations": {
"vscode": {
"extensions": [
// Highlighting for Parser/Python.asdl.
"brettcannon.zephyr-asdl",
// Highlighting for configure.ac.
"maelvalais.autoconf",
// C auto-complete.
"ms-vscode.cpptools",
// To view HTML build of docs.
"ms-vscode.live-server",
// Python auto-complete.
"ms-python.python"
],
"settings": {
"C_Cpp.default.compilerPath": "/usr/bin/clang",
"C_Cpp.default.cStandard": "c11",
"C_Cpp.default.defines": [
"CONFIG_64",
"Py_BUILD_CORE"
],
"C_Cpp.default.includePath": [
"${workspaceFolder}/*",
"${workspaceFolder}/Include/**"
],
// https://github.com/microsoft/vscode-cpptools/issues/10732
"C_Cpp.errorSquiggles": "disabled",
"editor.insertSpaces": true,
"editor.rulers": [
80
],
"editor.tabSize": 4,
"editor.trimAutoWhitespace": true,
"files.associations": {
"*.h": "c"
},
"files.encoding": "utf8",
"files.eol": "\n",
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true,
"python.analysis.diagnosticSeverityOverrides": {
// Complains about shadowing the stdlib w/ the stdlib.
"reportShadowedImports": "none",
// Doesn't like _frozen_importlib.
"reportMissingImports": "none"
},
"python.analysis.extraPaths": [
"Lib"
],
"python.defaultInterpreterPath": "./python",
"[restructuredtext]": {
"editor.tabSize": 3
}
}
}
}
}
从上面往下看,一开始指定了构建使用的dockerfile,即使用当前目录的Dockerfile,随后定义了编译前、编译中、编译后所执行的命令,其中关键的是updateContentCommand中的编译命令:
./configure --config-cache --with-pydebug && make -s -j `nproc`
就是这条命令执行了python3的编译。
以上是我对dev container的感性认识,不要较真,下面记录一下使用dev container编译python3.13.2的过程。
只需要三步:
- 安装docker
- vscode安装dev container插件
- 使用vscode自动构建
1,2步自不必说,关键在于构建devcontainer的一步,从devcontainer.json中我们可以知道构建devcontainer需要先build docker容器,然后执行编译命令,其中可能会有几个问题点。
第一,docker镜像源问题,有可能下载镜像下载不下来,需要更换docker镜像源,操作如下:
编辑/etc/docker/daemon.json,写入:
{
"registry-mirrors": [
"https://docker.1ms.run",
"https://docker.xuanyuan.me"
]
}
执行命令:
sudo systemctl daemon-reload
sudo systemctl restart docker
第二,WASI和WASMTIME下载不下来,还是由于网络问题,源码中是从github上下载的,有可能你开了科技,或者更换网络,都无法使用Dockerfile中的curl命令把它成功下载下来,这里是这样解决的:
首先,离线下载wasi_sdk和wasmtime,就是dockerfile中的链接,构建时会在日志里打印出来。
然后,在本地开http服务器,将下载下来的包放入http服务器的目录中,修改dockerfile中的下载链接,然后再次构建即可成功。
开http服务器使用python自带的http服务器即可,好用:
python3 -m http.server
它会在本地0000:8000地址上开一个http服务,所以我们要把dockerfile中的下载链接改成本地,比如我本地ip是8.8.8.8,修改Dockerfile如下:
......
RUN mkdir ${WASI_SDK_PATH} && \
curl --location http://8.8.8.8:8000/wasi-sdk-${WASI_SDK_VERSION}.0-x86_64-linux.tar.gz | \
tar --strip-components 1 --directory ${WASI_SDK_PATH} --extract --gunzip
RUN mkdir --parents ${WASMTIME_HOME} && \
curl --location "http://8.8.8.8:8000/wasmtime-v${WASMTIME_VERSION}-${WASMTIME_CPU_ARCH}-linux.tar.xz" | \
xz --decompress | \
tar --strip-components 1 --directory ${WASMTIME_HOME} -x && \
ln -s ${WASMTIME_HOME}/wasmtime /usr/local/bin
修改完毕后重新打开vscode触发devcontainer自动构建,最终构建成功。
从vscode中打开终端,编译出的python可执行文件位于当前目录下:
[root@7e8983e25582 Python-3.13.2]# ls
Android InternalDocs Makefile Modules Parser Tools config.cache config.sub install-sh pyconfig.h python-config.py
Doc LICENSE Makefile.pre Objects Programs _bootstrap_python config.guess configure libpython3.13d.a pyconfig.h.in python-gdb.py
Grammar Lib Makefile.pre.in PC Python aclocal.m4 config.log configure.ac platform python
Include Mac Misc PCbuild README.rst build config.status iOS pybuilddir.txt python-config
[root@7e8983e25582 Python-3.13.2]# pwd
/workspaces/Python-3.13.2
[root@7e8983e25582 Python-3.13.2]# ./python
Python 3.13.2 (main, Mar 28 2025, 09:03:17) [Clang 18.1.8 (Fedora 18.1.8-2.fc40)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
节省一点生命,dev container帮我们完成了编译工作,使我们可以把精力放在源码上。