|
1 | | -# PYTHON image |
2 | | -# Use the official Docker Python image because it has the absolute latest bugfix version of Python |
3 | | -# it has the absolute latest system packages |
4 | | -# it’s based on Debian Bookworm (Debian 12), released June 2023 |
5 | | -# Initial Image size is 51MB |
6 | | -# At the end Image size is 156MB |
| 1 | +################################################################################ |
| 2 | +# BASE # |
| 3 | +################################################################################ |
| 4 | +FROM python:3.11-slim-bookworm AS base |
7 | 5 |
|
8 | | -# I did not recommed using an alpine image because it lacks the package installer pip and the support for installing |
9 | | -# wheel packages, which are both needed for installing applications like Pandas and Numpy. |
| 6 | +ARG POETRY_VERSION=1.8.3 |
| 7 | +ARG UID=1000 |
| 8 | +ARG GID=1000 |
| 9 | + |
| 10 | +# Where python should look for packages and modules when using import |
| 11 | +ENV PYTHONPATH="/app" |
10 | 12 |
|
11 | | -# The base layer will contain the dependencies shared by the other layers |
12 | | -FROM python:3.11-slim-bookworm as base |
| 13 | +# Ensure the stdout and stderr streams are sent straight to terminal |
| 14 | +ENV PYTHONUNBUFFERED=1 |
13 | 15 |
|
14 | | -# Allowing the argumenets to be read into the dockerfile. Ex: .env > compose.yml > Dockerfile |
15 | | -ARG POETRY_VERSION |
16 | | -# true = development / false = production |
17 | | -ARG DEV |
| 16 | +# Extend the socket timeout. Default would be 15s |
| 17 | +ENV PIP_DEFAULT_TIMEOUT=100 |
| 18 | + |
| 19 | +RUN groupadd -g ${GID} -o app |
| 20 | +RUN useradd -m -d /app -u ${UID} -g ${GID} -o -s /bin/bash app |
| 21 | + |
| 22 | +# RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends \ |
| 23 | +# vim-tiny |
18 | 24 |
|
19 | | -# Set the working directory to /app |
20 | 25 | WORKDIR /app |
21 | 26 |
|
22 | | -# Use this page as a reference for python and poetry environment variables: https://docs.python.org/3/using/cmdline.html#envvar-PYTHONUNBUFFERED |
23 | | -# Ensure the stdout and stderr streams are sent straight to terminal, then you can see the output of your application |
24 | | -ENV PYTHONUNBUFFERED=1\ |
25 | | - # Avoid the generation of .pyc files during package install |
26 | | - # Disable pip's cache, then reduce the size of the image |
27 | | - PIP_NO_CACHE_DIR=off \ |
28 | | - # Save runtime because it is not look for updating pip version |
29 | | - PIP_DISABLE_PIP_VERSION_CHECK=on \ |
30 | | - PIP_DEFAULT_TIMEOUT=100 \ |
31 | | - # Disable poetry interaction |
32 | | - POETRY_NO_INTERACTION=1 \ |
33 | | - POETRY_VIRTUALENVS_CREATE=1 \ |
34 | | - POETRY_VIRTUALENVS_IN_PROJECT=1 \ |
35 | | - POETRY_CACHE_DIR=/tmp/poetry_cache |
| 27 | +CMD ["tail", "-f", "/dev/null"] |
| 28 | + |
| 29 | +################################################################################ |
| 30 | +# POETRY |
| 31 | +################################################################################ |
| 32 | +# |
| 33 | +# Both BUILD and DEVELOPMENT need poetry |
| 34 | +# |
| 35 | +FROM base AS poetry |
36 | 36 |
|
37 | 37 | RUN pip install poetry==${POETRY_VERSION} |
38 | 38 |
|
39 | | -# Install the app. Just copy the files needed to install the dependencies |
40 | | -COPY pyproject.toml poetry.lock README.md ./ |
| 39 | +# Ensure that the virtual environment directory is in the project. This path |
| 40 | +# will be be `/app/.venv/` |
| 41 | +ENV POETRY_VIRTUALENVS_IN_PROJECT=1 |
41 | 42 |
|
42 | | -# Poetry cache is used to avoid installing the dependencies every time the code changes, we will keep this folder in development environment and remove it in production |
43 | | -# --no-root, poetry will install only the dependencies avoiding to install the project itself, we will install the project in the final layer |
44 | | -# --without dev to avoid installing dev dependencies, we do not need test and linters in production environment |
45 | | -# --with dev to install dev dependencies, we need test and linters in development environment |
46 | | -# --mount, mount a folder for plugins with poetry cache, this will speed up the process of building the image |
47 | | -RUN if [ {${DEV}} ]; then \ |
48 | | - echo "Installing dev dependencies"; \ |
49 | | - poetry install --no-root --with dev \ |
50 | | - else \ |
51 | | - echo "Skipping dev dependencies"; \ |
52 | | - poetry install --no-root --without dev && rm -rf ${POETRY_CACHE_DIR}; \ |
53 | | - fi |
54 | | - |
55 | | -# Set up our final runtime layer |
56 | | -FROM python:3.11-slim-bookworm as runtime |
| 43 | +# Create the virtual environment if it does not already exist |
| 44 | +ENV POETRY_VIRTUALENVS_CREATE=1 |
57 | 45 |
|
58 | | -ARG UID=1000 |
59 | | -ARG GID=1000 |
| 46 | +################################################################################ |
| 47 | +# BUILD # |
| 48 | +################################################################################ |
| 49 | +# |
| 50 | +# This step uses poetry to generate a requirements.txt file for PRODUCTION |
| 51 | +# |
| 52 | +FROM poetry AS build |
60 | 53 |
|
61 | | -# Create our users here in the last layer or else it will be lost in the previous discarded layers |
62 | | -# Create a system group named "app_user" with the -r flag |
63 | | -RUN groupadd -g ${GID} -o app |
64 | | -RUN useradd -m -d /app -u ${UID} -g ${GID} -o -s /bin/bash app |
65 | | -RUN mkdir -p /venv && chown ${UID}:${GID} /venv |
66 | | -RUN which pip && sleep 10 |
| 54 | +# README.md is needed so that poetry command will work. |
| 55 | +COPY pyproject.toml poetry.lock README.md ./ |
| 56 | + |
| 57 | +RUN poetry export --without dev -f requirements.txt --output requirements.txt |
67 | 58 |
|
68 | | -# By adding /venv/bin to the PATH the dependencies in the virtual environment |
69 | | -# are used |
70 | | -ENV VIRTUAL_ENV=/venv \ |
71 | | - PATH="/venv/bin:$PATH" |
| 59 | +################################################################################ |
| 60 | +# DEVELOPMENT # |
| 61 | +################################################################################ |
| 62 | +# |
| 63 | +# In development we want poetry in the container, so it inherits from the POETRY |
| 64 | +# step. This step is the place to install development-only sytem dependencies |
| 65 | +# |
| 66 | +FROM poetry AS development |
72 | 67 |
|
73 | | -COPY --chown=${UID}:${GID} --from=base "/app/.venv" ${VIRTUAL_ENV} |
| 68 | +# RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends \ |
| 69 | +# wget\ |
74 | 70 |
|
75 | | -# Switch to the non-root user "user" |
76 | 71 | USER app |
77 | 72 |
|
78 | | -WORKDIR /app |
| 73 | +################################################################################ |
| 74 | +# PRODUCTION # |
| 75 | +################################################################################ |
| 76 | +FROM base AS production |
| 77 | + |
| 78 | +# Setting this to 'off' actually turns off the cache. This is set to decrease |
| 79 | +# the size of the image. |
| 80 | +ENV PIP_NO_CACHE_DIR=off |
| 81 | + |
| 82 | +# Speed up pip usage by not checking for the version |
| 83 | +ENV PIP_DISABLE_PIP_VERSION_CHECK=on |
79 | 84 |
|
80 | 85 | COPY --chown=${UID}:${GID} . /app |
| 86 | +COPY --chown=${UID}:${GID} --from=build "/app/requirements.txt" /app/requirements.txt |
81 | 87 |
|
82 | | -CMD ["tail", "-f", "/dev/null"] |
| 88 | +RUN pip install -r /app/requirements.txt |
| 89 | + |
| 90 | +USER app |
0 commit comments