为使用了私有仓库的 Python 项目构建 Docker 镜像
在真实的 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 容器中的。为此,可使用“多阶段构建”:
- 在第一个阶段安装模块
- 把第一个阶段安装的模块,复制到第二阶段中
示例如下:
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》 进行挂载。