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
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.