为什么多阶段 docker 图像比单阶段大?
Why multi-stage docker image is bigger than single stage?
我创建了一个微服务 (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)。知道在这种情况下可能出什么问题吗?
在你是第一个例子中你是 运行
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 包,一种行之有效的方法是从包中构建一个 wheel:
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
...
我创建了一个微服务 (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)。知道在这种情况下可能出什么问题吗?
在你是第一个例子中你是 运行
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 包,一种行之有效的方法是从包中构建一个 wheel:
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
...