pythondockerdockerfilealpine-linuxpipenv

How to make lightweight docker image for python app with pipenv


I can produce working image for my python app with following simple Dockerfile:

FROM python:3.7
WORKDIR /myapp
COPY Pipfile* ./
RUN pip install pipenv
RUN pipenv install --system --deploy
COPY src .
CMD ["python3", "app.py"]

However, it will produce ~1 GB image, which can contain temporary files, and is heavy to deploy. And I only need full python image for building purposes. My app can successfully run on alpine variant, so I can make two-pass Dockerfile:

FROM python:3.7 as builder
COPY Pipfile* ./
RUN pipenv lock --requirements > requirements.txt
RUN python3 -m venv /venv
RUN /venv/bin/pip install --upgrade pip
RUN /venv/bin/pip install -r requirements.txt

FROM python:3.7-alpine
COPY --from=builder /venv /venv
WORKDIR /myapp
COPY src .
CMD ["/venv/bin/python3", "app.py"]

So far so good, it also works, being 6 times smaller. But this scheme was considered as some "stub", having some drawbacks:


How to combine these two approaches, to get lightweitht alpine-based image with pipenv, lacking mentioned drawbacks?

Or can you offer your production Dockerfile ideas?


Solution

  • The problem comes when you need things like ciso8601, or some libraries, requiring build process. Build tools are not "incorporated" into the both slim and alpine variants, for low-size footprint.

    So to install deps, you'll have to:

    And do that 3 actions inside a single RUN layer, like following:

    FROM python:3.7-slim
    
    WORKDIR /app
    
    # both files are explicitly required!
    COPY Pipfile Pipfile.lock ./
    
    RUN pip install pipenv && \
      apt-get update && \
      apt-get install -y --no-install-recommends gcc python3-dev libssl-dev && \
      pipenv install --deploy --system && \
      apt-get remove -y gcc python3-dev libssl-dev && \
      apt-get autoremove -y && \
      pip uninstall pipenv -y
    
    COPY app ./
    
    CMD ["python", "app.py"]
    

    So that would result in perfectly working ~200MiB sized image, which is

    At the time, we're fine with slim (debian buster) build variants, preferring slim over alpine (for most compatibility). If you're really up to further size optimization, I'd recommend you to take a look at some excellent builds of these guys: