为什么多阶段docker映像比单阶段更大?

时间:2020-02-17 21:28:38

标签: python docker docker-multi-stage-build

我创建了一个微服务(https://github.com/staticdev/enelvo-microservice),该服务需要克隆git存储库以创建docker映像,使用单阶段Dockerfile,最终映像具有759MB:

FROM python:3.7.6-slim-stretch

# set the working directory to /app
WORKDIR /app

# copy the current directory contents into the container at /app
COPY . /app

RUN apt-get update && apt-get install -y git \
 && pip install -r requirements.txt \
 && git clone https://github.com/tfcbertaglia/enelvo.git enelvo-src \
 && cd enelvo-src \
 && python setup.py install \
 && cd .. \
 && mv enelvo-src/enelvo enelvo \
 && rm -fr enelvo-src

EXPOSE 50051

# run app.py when the container launches
CMD ["python", "app.py"]

我已经尝试了使用多阶段构建(https://blog.bitsrc.io/a-guide-to-docker-multi-stage-builds-206e8f31aeb8)来减少没有git和apt-get列表(来自更新)的图像大小的方法:

FROM python:3.7.6-slim-stretch as cloner

RUN apt-get update && apt-get install -y git \
 && git clone https://github.com/tfcbertaglia/enelvo.git enelvo-src

FROM python:3.7.6-slim-stretch

COPY --from=cloner /enelvo-src /app/enelvo-src

# set the working directory to /app
WORKDIR /app

# copy the current directory contents into the container at /app
COPY . /app

RUN pip install -r requirements.txt \
 && cd enelvo-src \
 && python setup.py install \
 && cd .. \
 && mv enelvo-src/enelvo enelvo \
 && rm -fr enelvo-src

EXPOSE 50051

# run app.py when the container launches
CMD ["python", "app.py"]

问题在于,这样做之后,最终大小甚至更大(815MB)。有什么想法在这种情况下会出错吗?

1 个答案:

答案 0 :(得分:1)

在第一个示例中,您正在运行

RUN git clone https://github.com/tfcbertaglia/enelvo.git enelvo-src \
    ... \
 && rm -fr enelvo-src

,因此enelvo-src树永远不会在该特定RUN指令之外存在;在Docker可以在其上构建层之前将其删除。

在第二个示例中,您正在运行

COPY --from=cloner /enelvo-src /app/enelvo-src
RUN rm -fr enelvo-src

在第一步之后,Docker内部创建了一个包含该源树内容的图像层。后续的RUN rm实际上并没有使图像变小,它只是记录说从技术上讲,较早层中的内容不再是文件系统的一部分。

通常,使用多阶段构建的标准方法是在早期阶段尽可能多地进行构建,并且仅将COPY的最终结果添加到运行时映像中。对于Python软件包,一种行之有效的方法是在软件包之外构建disable assertions

FROM python:3.7.6-slim-stretch as build
WORKDIR /build
RUN apt-get update && apt-get install -y git \
 && git clone https://github.com/tfcbertaglia/enelvo.git enelvo-src
 && ...
 && python setup.py bdist_wheel  # (not "install")

FROM python:3.7.6-slim-stretch
WORKDIR /app
COPY --from=build /build/dist/wheel/enelvo*.whl .
RUN pip install enelvo*.whl
...