Docker如何仅在发生更改时运行pip requirements.txt?

Posted

技术标签:

【中文标题】Docker如何仅在发生更改时运行pip requirements.txt?【英文标题】:Docker how to run pip requirements.txt only if there was a change? 【发布时间】:2016-03-27 16:50:31 【问题描述】:

在 Dockerfile 中,我有一个安装 requirements.txt 的层:

FROM python:2.7
RUN pip install -r requirements.txt

当我构建 docker 映像时,它会运行整个过程不管对此文件所做的任何更改。

如何确保 Docker 仅在文件发生更改时才运行 pip install -r requirements.txt

Removing intermediate container f98c845d0f05
Step 3 : RUN pip install -r requirements.txt
 ---> Running in 8ceb63abaef6
Collecting https://github.com/tomchristie/django-rest-framework/archive/master.zip (from -r requirements.txt (line 30))
  Downloading https://github.com/tomchristie/django-rest-framework/archive/master.zip
Collecting Django==1.8.7 (from -r requirements.txt (line 1))

【问题讨论】:

请发布docker build(和您的Dockerfile)的输出。据推测,这是您构建过程中较早的步骤破坏了缓存,导致此步骤运行。 用我目前拥有的所有内容更新 OP 只是这一步没有用。请发布 complete 输出(或至少 Dockerfile)。 【参考方案1】:

我假设在您的构建过程中的某个时刻,您将使用COPYADD 将整个应用程序复制到Docker 映像中:

COPY . /opt/app
WORKDIR /opt/app
RUN pip install -r requirements.txt

问题在于,每次将整个应用程序复制到映像中时,都会使 Docker 构建缓存失效。这也会使所有后续构建步骤的缓存失效。

为防止这种情况发生,我建议在将整个应用程序添加到映像之前,在单独的构建步骤中仅复制 requirements.txt 文件:

COPY requirements.txt /opt/app/requirements.txt
WORKDIR /opt/app
RUN pip install -r requirements.txt
COPY . /opt/app
# continue as before...

由于需求文件本身可能很少更改,因此在将应用程序代码添加到图像之前,您将能够使用缓存层。

【讨论】:

作为一般准则,我认为COPY 优于ADD,除非您特别需要ADD 的行为。 @Metropolis,你是完全正确的。感谢您的提示。 同意@Metropolis。仅当 <src> 文件夹包含任何需要解压缩或需要支持远程 URL 处理的存档时,才需要 ADDsource code【参考方案2】:

这个在Docker自己的“Best practices for writing Dockerfiles”中直接提到:

如果您有多个使用不同文件的 Dockerfile 步骤 您的上下文,单独复制它们,而不是一次全部复制。这 将确保每个步骤的构建缓存仅失效(强制 重新运行的步骤),如果特别需要的文件发生变化。

例如:

COPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt
COPY . /tmp/

导致 RUN 步骤的缓存失效次数少于将 副本。 /tmp/ 在它之前。

【讨论】:

【参考方案3】:

作为一种更快捷的方式来运行 requirements.txt 文件而不输入“yes”来确认库的安装,您可以重写为:

COPY requirements.txt ./
RUN pip install -y -r requirements.txt
COPY ./"dir"/* .

【讨论】:

以上是关于Docker如何仅在发生更改时运行pip requirements.txt?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以仅在数据发生更改时更新 mysql 视图?

如何调试仅在应用程序关闭时发生的崩溃? (德尔福)

仅在 8080 上运行的 Spring Boot docker?

在 docker 构建中使用 pip 缓存目录

合并 - 仅在值更改时更新

仅在项目发生更改时添加编译时间戳 (C)