You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Docker中仅安装pyproject.toml依赖而不安装目标Python包?

问题与解决方案

问题描述

我有一个需要在Dockerfile中安装的Python包,其pyproject.toml配置如下:

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "bar"
dependencies = [
    "pandas",
]

[project.optional-dependencies]
foo = [
    "matplotlib",
]

当前Dockerfile内容为:

# ...
WORKDIR /app
COPY . /app
RUN pip install /app

每次构建都会重新安装pandas这类依赖,但pyproject.toml极少修改,我希望避免重复安装以节省开发时间。需要实现仅安装pyproject.toml中列出的依赖,无需复制全部文件并安装bar包,同时需满足:

  • 不使用poetry等其他工具
  • 不创建requirements.txt,也不在pyproject.toml中使用dynamic关键字(希望依赖列表集中在同一文件)

期望的实现逻辑类似:

# ...
WORKDIR /app
COPY ./pyproject.toml /app/
RUN pip install --requirements-from /app/pyproject.toml  # <-- 此处需实现
COPY . /app
RUN pip install /app  # <-- 仅安装bar包,依赖已提前安装

解决方案

这里提供两种符合要求的实现方式,都能利用Docker缓存,只有pyproject.toml修改时才会重新安装依赖:

方法一:用pip模拟安装提取依赖

通过pip install --dry-run的输出提取依赖列表,再单独安装:

# ...
WORKDIR /app
# 只复制pyproject.toml,触发缓存机制
COPY pyproject.toml .
# 提取核心依赖并安装
RUN pip install --dry-run . | grep -E '^Would install' | sed 's/Would install //' | xargs pip install
# 要是需要安装可选依赖(比如foo),把上面的命令改成:
# RUN pip install --dry-run .[foo] | grep -E '^Would install' | sed 's/Would install //' | xargs pip install

# 复制全部代码文件
COPY . .
# 仅安装bar包本身,跳过依赖(已经提前装好了)
RUN pip install --no-deps .

方法二:利用setuptools生成临时依赖信息

通过生成egg-info文件让pip识别依赖,再安装:

# ...
WORKDIR /app
COPY pyproject.toml .
# 生成egg-info文件,让pip能读取到pyproject.toml里的依赖
RUN python -m setuptools egg_info
# 安装核心依赖(-e表示可编辑模式,--no-build-isolation避免重复构建环境)
RUN pip install -e . --no-build-isolation
# 安装可选依赖的话,改成:pip install -e .[foo] --no-build-isolation

COPY . .
# 安装包本身,跳过依赖
RUN pip install --no-deps .

关键说明

  • 两种方法都靠Docker的分层缓存实现:只要pyproject.toml没改动,依赖安装的步骤就会直接用缓存,不用重新执行
  • --no-deps参数确保最后安装bar包时不会重复安装已有的依赖
  • 可选依赖的安装语法和直接安装包时一致,不用额外维护其他文件

内容的提问来源于stack exchange,提问作者obk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 21:00:53