Docker 如何仅在发生变化时 运行 pip requirements.txt?

Docker how to run pip requirements.txt only if there was a change?

在 Docker 文件中,我有一层安装 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))

我假设在构建过程中的某个时刻,您正在使用 COPYADD:[=15= 将整个应用程序复制到 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...

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

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

If you have multiple Dockerfile steps that use different files from your context, COPY them individually, rather than all at once. This will ensure that each step’s build cache is only invalidated (forcing the step to be re-run) if the specifically required files change.

For example:

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

Results in fewer cache invalidations for the RUN step, than if you put the COPY . /tmp/ before it.

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

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