-
Notifications
You must be signed in to change notification settings - Fork 2
/
Dockerfile
109 lines (85 loc) · 4.27 KB
/
Dockerfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# References, thanks max-pfeiffer:
# https://github.com/max-pfeiffer/python-poetry/blob/main/build/Dockerfile
# https://github.com/max-pfeiffer/uvicorn-poetry/blob/main/build/Dockerfile
# https://github.com/max-pfeiffer/uvicorn-poetry/blob/main/examples/fast_api_multistage_build/Dockerfile
# References: using official Python images
# https://hub.docker.com/_/python
ARG OFFICIAL_PYTHON_IMAGE=python:3.12.2-slim-bullseye
FROM ${OFFICIAL_PYTHON_IMAGE} as poetry-install-build-stage
ARG POETRY_VERSION=1.8.2
# References:
# https://pip.pypa.io/en/stable/topics/caching/#avoiding-caching
# https://pip.pypa.io/en/stable/cli/pip/?highlight=PIP_NO_CACHE_DIR#cmdoption-no-cache-dir
# https://pip.pypa.io/en/stable/cli/pip/?highlight=PIP_DISABLE_PIP_VERSION_CHECK#cmdoption-disable-pip-version-check
# https://pip.pypa.io/en/stable/cli/pip/?highlight=PIP_DEFAULT_TIMEOUT#cmdoption-timeout
# https://pip.pypa.io/en/stable/topics/configuration/#environment-variables
# https://python-poetry.org/docs/#installation
# https://refspecs.linuxfoundation.org/FHS_2.3/fhs-2.3.html#OPTADDONAPPLICATIONSOFTWAREPACKAGES
ENV PIP_NO_CACHE_DIR=off \
PIP_DISABLE_PIP_VERSION_CHECK=on \
PIP_DEFAULT_TIMEOUT=100 \
POETRY_VERSION=${POETRY_VERSION} \
POETRY_HOME="/opt/poetry"
RUN apt-get update \
&& apt-get install --no-install-recommends -y \
build-essential
# https://python-poetry.org/docs/#installing-manually
RUN python -m venv ${POETRY_HOME}
RUN ${POETRY_HOME}/bin/pip install -U pip setuptools
RUN ${POETRY_HOME}/bin/pip install "poetry==${POETRY_VERSION}"
FROM ${OFFICIAL_PYTHON_IMAGE} as server-setup-build-stage
ENV PATH="/opt/poetry/bin:$PATH"
COPY --from=poetry-install-build-stage /opt/poetry /opt/poetry/
ARG APPLICATION_SERVER_PORT=8000
# https://docs.python.org/3/using/cmdline.html#envvar-PYTHONUNBUFFERED
ENV PYTHONUNBUFFERED=1 \
# https://docs.python.org/3/using/cmdline.html#envvar-PYTHONDONTWRITEBYTECODE
PYTHONDONTWRITEBYTECODE=1 \
PYTHONPATH=/application_root \
# https://python-poetry.org/docs/configuration/#virtualenvsin-project
POETRY_VIRTUALENVS_IN_PROJECT=true \
POETRY_CACHE_DIR="/application_root/.cache" \
VIRTUAL_ENVIRONMENT_PATH="/application_root/.venv" \
APPLICATION_SERVER_PORT=$APPLICATION_SERVER_PORT
# Adding the virtual environment to PATH in order to "activate" it.
# https://docs.python.org/3/library/venv.html#how-venvs-work
ENV PATH="$VIRTUAL_ENVIRONMENT_PATH/bin:$PATH"
# Principle of least privilege: create a new user for running the application
RUN groupadd -g 1001 python_application && \
useradd -r -u 1001 -g python_application python_application
COPY ./scripts/start.sh /start
RUN sed -i 's/\r$//g' /start
RUN chmod +x /start
COPY ./scripts/celery.sh /celery
RUN sed -i 's/\r$//g' /celery
RUN chmod +x /celery
COPY ./scripts/flower.sh /flower
RUN sed -i 's/\r$//g' /flower
RUN chmod +x /flower
# Set the WORKDIR to the application root.
# https://www.uvicorn.org/settings/#development
# https://docs.docker.com/engine/reference/builder/#workdir
WORKDIR ${PYTHONPATH}
RUN chown python_application:python_application ${PYTHONPATH}
# Create cache directory and set permissions because user 1001 has no home
# and poetry cache directory.
# https://python-poetry.org/docs/configuration/#cache-directory
RUN mkdir ${POETRY_CACHE_DIR} && chown python_application:python_application ${POETRY_CACHE_DIR}
# Document the exposed port
# https://docs.docker.com/engine/reference/builder/#expose
EXPOSE ${APPLICATION_SERVER_PORT}
# Use the unpriveledged user to run the application
USER 1001
# Run the uvicorn application server.
CMD /start
FROM server-setup-build-stage as install-dependencies-build-stage
# install [tool.poetry.dependencies]
# this will install virtual environment into /.venv because of POETRY_VIRTUALENVS_IN_PROJECT=true
# see: https://python-poetry.org/docs/configuration/#virtualenvsin-project
COPY ./poetry.lock ./pyproject.toml /application_root/
RUN poetry install --no-interaction --no-root --without dev
FROM server-setup-build-stage as production-image
# Copy virtual environment
COPY --chown=python_application:python_application --from=install-dependencies-build-stage /application_root/.venv /application_root/.venv
# Copy application files
COPY --chown=python_application:python_application /internal /application_root/internal/