使用dev container搭建python3编译环境

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的过程。

只需要三步:

  1. 安装docker
  2. vscode安装dev container插件
  3. 使用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帮我们完成了编译工作,使我们可以把精力放在源码上。

### 如何在 Docker 中设置 Python 虚拟环境 为了在 Docker 容器中配置虚拟 Python 环境,可以按照以下方法操作: #### 创建自定义的 Docker 镜像 通过编写 `Dockerfile` 文件来创建一个包含虚拟环境的镜像。以下是具体的实现方式。 --- #### 1. 拉取基础镜像并安装依赖项 首先,在 `Dockerfile` 中指定基础镜像,并更新必要的软件包。 ```dockerfile FROM python:3.9-slim RUN apt-get update && apt-get install -y build-essential libssl-dev libffi-dev python3-dev ``` 此部分代码用于拉取官方发布的 Python 基础镜像,并安装编译扩展所需的工具和库[^2]。 --- #### 2. 设置工作目录 为项目设定一个固定的工作路径,方便后续挂载宿主机上的文件到容器内部。 ```dockerfile WORKDIR /app ``` --- #### 3. 初始化虚拟环境 利用 Python 自带的 `venv` 或者第三方工具如 `virtualenv` 来初始化虚拟环境。 ```dockerfile RUN python3 -m venv /opt/venv ENV PATH="/opt/venv/bin:$PATH" ``` 上述命令会在 `/opt/venv` 下创建一个新的虚拟环境,并将其加入系统的 `PATH` 变量以便全局可用[^3]。 --- #### 4. 复制需求文件并安装依赖 将项目的 `requirements.txt` 文件复制到容器内,并运行 pip 进行依赖安装。 ```dockerfile COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt ``` 这一步骤确保所有的外部库都被正确加载至虚拟环境中[^4]。 --- #### 5. 映射宿主机文件夹到容器 当启动容器时,可以通过 `-v` 参数把本地开发机器上的源码同步给容器使用。例如: ```bash docker run -it --rm -v $(pwd):/app your_image_name bash ``` 这样做的好处是可以实时编辑宿主机上的代码而无需重新构建整个镜像[^1]。 --- #### 示例完整的 Dockerfile 综合以上各点,下面给出一个完整的例子供参考: ```dockerfile # Base Image FROM python:3.9-slim # Install system dependencies RUN apt-get update && \ apt-get install -y build-essential libssl-dev libffi-dev python3-dev # Set working directory inside container WORKDIR /app # Create virtual environment and set it as default RUN python3 -m venv /opt/venv ENV PATH="/opt/venv/bin:$PATH" # Copy requirement file into image context & install packages within the venv COPY requirements.txt . RUN pip install --upgrade pip && \ pip install --no-cache-dir -r requirements.txt # Optional step to copy application code (if not using volume mount) # COPY . . CMD ["python", "-m", "http.server"] # Replace with actual command or entrypoint script. ``` --- ### 总结 通过这种方式可以在 Docker 容器里安全隔离地维护独立于其他应用之外的 Python 版本及其关联模块集合;同时借助 PyCharm IDE 的远程调试功能进一步简化日常编码流程^。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值