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:
- Install build tools
- Deploy dependencies from Pipfile.lock system-wide
- Uninstall build tools and clean caches
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"]
- Manipulating build system would cost you around 300MiB and some extra time
- Uninstalling pipenv would save you another 20MiB (which is 10% of resulting size).
- Separating
RUNcommands would not delete data from layers, and would result in ~500MiB image. That's docker specifics.
So that would result in perfectly working ~200MiB sized image, which is
- 5 times less than original
python:3.7, (that is >1.0GiB) - Has no alpine incompabilities (these are typically tied to glibc replacement)
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:
- Alpine Python
- 12.7MiB MariaDB
Videos
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:
- Install build tools
- Deploy dependencies from Pipfile.lock system-wide
- Uninstall build tools and clean caches
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"]
- Manipulating build system would cost you around 300MiB and some extra time
- Uninstalling pipenv would save you another 20MiB (which is 10% of resulting size).
- Separating
RUNcommands would not delete data from layers, and would result in ~500MiB image. That's docker specifics.
So that would result in perfectly working ~200MiB sized image, which is
- 5 times less than original
python:3.7, (that is >1.0GiB) - Has no alpine incompabilities (these are typically tied to glibc replacement)
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:
- Alpine Python
- 12.7MiB MariaDB
How about,
FROM python:3.7-alpine
WORKDIR /myapp
COPY Pipfile* ./
RUN pip install --no-cache-dir pipenv && \
pipenv install --system --deploy --clear
COPY src .
CMD ["python3", "app.py"]
- It utilises the smaller Alpine version.
- You won't have any unnecessary cache files left over using
--no-cache-diroption forpipand--clearoption forpipenv. - You also deploy outside of venv.
You can also add && pip uninstall pipenv -y after pipenv install --system --deploy --clear in the same RUN command to eliminate space taken by pipenv if that extra image size bothers you.