英文:
Dockerfile - why does removing build tools increase the size of the resulting image?
问题
我有一个 Dockerfile,看起来像这样 ...
```plaintext
# 拉取基础镜像
FROM python:3.9.17-slim-bullseye
# 设置环境变量
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# pip 安装阶段所需的二进制文件
RUN apt-get update && \
apt-get install --no-install-recommends -y gcc python3-dev default-libmysqlclient-dev && \
apt-get clean
# 创建并设置名为 `code` 的工作目录
RUN mkdir -p /code
WORKDIR /code
# 安装依赖
COPY requirements.txt /tmp/requirements.txt
# Pip 安装
RUN set -ex && \
pip install --upgrade pip && \
pip install -r /tmp/requirements.txt && \
rm -rf /root/.cache/
#
# pip 安装完成后,我们不再需要这些内容
RUN apt-get remove python3-dev default-libmysqlclient-dev gcc -y && \
apt-get autoremove -y
# 复制本地项目
COPY . /code/
# 暴露端口 8000
EXPOSE 8000
# 在端口 8000 上使用 gunicorn
CMD ["gunicorn", "--bind", ":8000", "--workers", "2", "django_project.wsgi"]
它生成一个大小为 576MB 的镜像。如果我移除这些行 ...
RUN apt-get remove python3-dev default-libmysqlclient-dev gcc -y && \
apt-get autoremove -y
... 它会生成一个 577MB 的镜像。
我原本希望通过移除构建工具显著减小镜像大小,但实际上反而略微增加了。我在 Dockerfile 中的做法是否显然有问题?
我通过执行以下命令来调用镜像构建
$ docker-compose build
... 使用一个看起来像这样的 docker-compose.yml ...
version: '3.3'
services:
fooweb:
build: .
network_mode: "host"
container_name: foo-web
command: gunicorn --bind 0.0.0.0:8000 config.wsgi --workers=4
volumes:
- .:/code
ports:
- 8000:8000
英文:
I have a Dockerfile which looks like this ...
# Pull base image
FROM python:3.9.17-slim-bullseye
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# Binaries needed for the pip install stage
RUN apt-get update && \
apt-get install --no-install-recommends -y gcc python3-dev default-libmysqlclient-dev &&\
apt-get clean
# Create and set work directory called `code`
RUN mkdir -p /code
WORKDIR /code
# Install dependencies
COPY requirements.txt /tmp/requirements.txt
# Pip install
RUN set -ex && \
pip install --upgrade pip && \
pip install -r /tmp/requirements.txt && \
rm -rf /root/.cache/
#
#Once pip is finished we don't need this stuff
RUN apt-get remove python3-dev default-libmysqlclient-dev gcc -y && \
apt-get autoremove -y
# Copy local project
COPY . /code/
# Expose port 8000
EXPOSE 8000
# Use gunicorn on port 8000
CMD ["gunicorn", "--bind", ":8000", "--workers", "2", "django_project.wsgi"]
and it produces a 576MB image. If I remove these lines ...
RUN apt-get remove python3-dev default-libmysqlclient-dev gcc -y && \
apt-get autoremove -y
... it produces a 577MB image.
I was hoping for a significant reduction in image size by removing the build tools but instead got a tiny increase. Is there something about what I'm doing in the Dockerfile which is obviously wrong ?
I invoke the image build by executing
$ docker-compose build
... using a docker-compose.yml which looks like this ...
version: '3.3'
services:
fooweb:
build: .
network_mode: "host"
container_name: foo-web
command: gunicorn --bind 0.0.0.0:8000 config.wsgi --workers=4
volumes:
- .:/code
ports:
- 8000:8000
答案1
得分: 3
每次对图像进行的更改都以图层的形式存储在最终图像中。因此,向基本图像添加工具将增加大小,稍后将其删除也会增加大小,因为这些步骤中的每一步都会更改先前的状态,更改被记录在图层中。
如果您想在图像内部构建,但不希望在最终图像中包含构建工具,那么我建议在基本图像中进行构建,然后将构建的工件复制到您实际部署的新图像中。
英文:
Every change to an image is stored as a layer in the resulting image. So adding tools to the base image will increase the size, and removing them later will also increase the size as each of those steps changes the previous state and the change is what is recorded in the layer.
If you want to build within an image, but not have the build tools in the final image then I would suggest to do a build in a base image and then copy the built artifacts into a new image that you are going to actually deploy.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论