首页 > 解决方案 > Dockerfile - 缓存包以更快地重建?

问题描述

我有一个构建 RESTApi 的 Dockerfile。每当我更改代码中的一行代码并想要重建容器时,所有内容都会从 0 开始安装(代码位于 app 文件夹中)。这是我的 Dockerfile:

# Use the Python3.7.2 image
FROM python:3.7.2-stretch

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app 
ADD . /app

# grab the key that LLVM use to GPG-sign binary distributions
RUN apt-get update && \
    apt-get install -y software-properties-common && \
    rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get install -y apt-utils && apt-get install -y curl
RUN apt -y install clang


# Install Mono (careful: Docker image runs on Debian 9)
RUN apt -y install apt-transport-https dirmngr gnupg ca-certificates
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
RUN echo "deb https://download.mono-project.com/repo/debian stable-stretch main" | tee /etc/apt/sources.list.d/mono-official-stable.list
RUN apt update
RUN apt -y install mono-complete

## Install python libraries
RUN apt-get -y install python3-pip
RUN pip install -r requirements.txt

RUN mono /app/pythonnet/tools/nuget/nuget.exe update -self

RUN git config --global http.proxy http://my.proxy.address:port
RUN /usr/bin/python3 -m pip install -U pycparser --user
RUN /usr/bin/python3 -m pip install -U pythonnet --user

# run the command to start uWSGI
CMD ["uwsgi", "app.ini"]

构建此映像需要很长时间,而且由于我只更改了几行代码,因此完全重建是一种不受欢迎的行为。

我跑来docker build -t flask_app .构建图像。无论如何只重新安装仅在我的代码库中进行更改的某些软件包?

标签: dockerflaskdockerfile

解决方案


docker build使用可以避免重建部分图像的层缓存。这里的基本规则是,一旦您COPY(或ADD)更改了文件,Dockerfile 中该行之后的所有内容将始终重复。指令之前的内容COPY,或者如果 Docker 可以告诉正在COPY编辑的文件没有更改,将被跳过(之前构建的层被重用)。

为了支持这一点,一个典型的 Dockerfile 布局如下:

FROM some-base-image
RUN commands to install OS-level dependencies
WORKDIR /app
COPY only files that declare language-level dependencies ./
RUN commands to install language-level dependencies
COPY . ./
RUN commands to build the application
CMD the single command to launch the application

请注意两个单独的COPY命令。RUN如果命令的文本没有更改,则重用操作系统级别的依赖项;如果特定文件未更改,则重用语言级别的依赖项;并且应用程序本身通常总是被重建。

在 Dockerfile 的上下文中,您应该让所有RUN apt-get ...命令在您执行任何操作之前COPY运行。(最好只有一个apt-get install; 重要的是让它与一个命令在同一个RUN命令中。apt-get update)然后requirements.txt复制文件和RUN pip install; 然后复制应用程序的其余部分。

FROM python:3.7.2-stretch
# Rearrange this so there is only one apt-get install line
# (Do you need all of these dependencies?)
RUN apt-get update && \
    apt-get install -y \
      apt-transport-https \
      apt-utils \
      ca-certificates \
      clang \
      curl \
      dirmngr \
      gnupg \
      software-properties-common
# Similarly install Mono (is it actually needed?)

# Copy and install just Python dependencies
WORKDIR /app
COPY requirements.txt .
# There are no requirements that aren't in the requirements.txt file
RUN pip install -r requirements.txt

# Copy the rest of the app in
COPY . .

# Standard runtime metadata
EXPOSE 8000
CMD ["uwsgi", "app.ini"]

推荐阅读