为使用了私有仓库的 Python 项目构建 Docker 镜像

2025-07-15#Python#Docker#Poetry

在真实的 Python 项目中,可能会使用私有的 PyPI 服务器上的模块。那么在构建容器时,就需要从私有PyPI服务器上下载模块,如果该服务器有密码保护,那么需要注意不要将密码遗留在镜像之中。文本假定使用 poetry 作为依赖管理工具,介绍如何安全地构建镜像。

操作步骤 🔗

使用 poetry 添加私有仓库 🔗

参考 poetry 的文档 《Repositories》,可使用如下方式添加仓库:

poetry source add --priority=supplemental foo https://pypi.example.org/simple/

此时,pyproject.toml 文件就会出现如下配置项:

[[tool.poetry.source]]
name = "foo"
url = "https://pypi.example.org/simple/"
priority = "supplemental"

配置登录凭证 🔗

假定仓库启用了 HTTP Basic 认证。

poetry 提供了多种方式与私有仓库进行认证,这里采纳其中一个方法:使用环境变量配置密码。那么可设置环境变量:

export POETRY_HTTP_BASIC_FOO_USERNAME=username
export POETRY_HTTP_BASIC_FOO_PASSWORD=password

配置之后,就可使用私有仓库的模块了。

编写 Dockerfile 🔗

如果在 Dockerfile 里定义参数保存私有仓库的密码,那么密码是会保存在 Docker 容器中的。为此,可使用“多阶段构建”:

  1. 在第一个阶段安装模块
  2. 把第一个阶段安装的模块,复制到第二阶段中

示例如下:

FROM python:3.13.5-alpine3.22 as builder

ARG POETRY_HTTP_BASIC_FOO_PASSWORD
ENV POETRY_HTTP_BASIC_FOO_PASSWORD=${POETRY_HTTP_BASIC_FOO_PASSWORD}
ENV POETRY_VIRTUALENVS_IN_PROJECT=true

WORKDIR /app

COPY pyproject.toml poetry.lock ./

RUN poetry install

FROM python:3.13.5-alpine3.22

WORKDIR /app

COPY --from=builder /app/.venv /app/.venv

ENV PATH="/app/.venv/bin:$PATH"

COPY . .

构建完成并发布后,清除本地镜像:

docker system prune -a -f

其他事宜 🔗

使用 uv 🔗

如果使用 uv 作为包管理工具,那么可参考 《Authentication》《Using alternative package indexes》,配置环境变量或者用其他方法。

将登录凭证挂载到构建镜像中 🔗

参考 Docker 官网中 《Build secrets》 进行挂载。