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:
- It has unnesesary extra
COPY --from=builder
step - It does not utilizes
pipenv
but needs alsopip
for installing (+1 extra step,pipenv lock
+pip install
is always slower than justpipenv install
) - It does not install system-wide, but into
/venv
, which is to be avoided inside a container - Minor: Build pollutes intermediate-images cache more, and requires downloading both image variants..
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?