1
- # Install shared system requirements (e.g. libmysql)
2
1
FROM python:3.11-slim as base
2
+ ARG UID=2000
3
+ ARG GID=2000
4
+ RUN addgroup --gid $GID nonroot && \
5
+ adduser --uid $UID --gid $GID --disabled-password --gecos "" nonroot
6
+ WORKDIR /app
7
+
3
8
# Creating a separate directory for venvs allows to easily
4
9
# copy them from the builder and to mount the application
5
10
# for local development
6
- RUN mkdir /poetryvenvs
7
- WORKDIR /app
11
+ RUN mkdir /poetryvenvs && chown nonroot:nonroot /poetryvenvs
12
+
13
+ # Install necessary runtime libraries (e.g. libmysql)
8
14
RUN apt-get update \
9
15
&& apt-get install -y --no-install-recommends \
10
16
make \
11
17
&& rm -rf /var/lib/apt/lists/*
12
18
13
- RUN pip install -U pip
14
- RUN pip install poetry
15
- RUN poetry config virtualenvs.path /poetryvenvs
19
+ # Update pip and install poetry
20
+ RUN pip install --no-cache-dir -U pip
21
+ RUN pip install --no-cache-dir -U poetry
16
22
17
- # Install shared build system requirements (gcc, library headers, etc.)
18
23
FROM base as base_builder
24
+ # Install build system requirements (gcc, library headers, etc.)
25
+ # for compiled Python requirements like psycopg2
19
26
RUN apt-get update \
20
27
&& apt-get install -y --no-install-recommends \
21
28
build-essential gcc git \
22
29
&& rm -rf /var/lib/apt/lists/*
23
30
24
- COPY pyproject.toml .
25
- COPY poetry.lock .
31
+ # From here we shouldn't need anymore a root user
32
+ # Switch to nonroot and config poetry
33
+ USER nonroot
34
+ RUN poetry config virtualenvs.path /poetryvenvs
35
+
36
+ COPY --chown=nonroot:nonroot pyproject.toml .
37
+ COPY --chown=nonroot:nonroot poetry.lock .
26
38
27
39
# Test image, contains all files and dependencies
28
40
FROM base_builder as test
29
- RUN poetry install --no-root -- with http,grpc,dev
30
- COPY . .
41
+ RUN poetry install --with http,grpc,dev
42
+ COPY --chown=nonroot:nonroot . .
31
43
32
44
# Installs requirements to run production http application
33
45
FROM base_builder as http_builder
@@ -39,25 +51,31 @@ RUN poetry install --no-root --with grpc
39
51
40
52
# Copy the shared python packages
41
53
FROM base as base_app
42
- COPY pyproject.toml .
43
- COPY poetry.lock .
44
- COPY alembic ./alembic
45
- COPY domains ./domains
46
- COPY storage ./storage
47
- COPY config.py .
48
- COPY di_container.py .
49
- COPY alembic.ini .
50
- COPY Makefile .
54
+ USER nonroot
55
+ RUN poetry config virtualenvs.path /poetryvenvs
56
+ COPY --chown=nonroot:nonroot pyproject.toml .
57
+ COPY --chown=nonroot:nonroot poetry.lock .
58
+ COPY --chown=nonroot:nonroot alembic ./alembic
59
+ COPY --chown=nonroot:nonroot domains ./domains
60
+ COPY --chown=nonroot:nonroot storage ./storage
61
+ COPY --chown=nonroot:nonroot config.py .
62
+ COPY --chown=nonroot:nonroot di_container.py .
63
+ COPY --chown=nonroot:nonroot alembic.ini .
64
+ COPY --chown=nonroot:nonroot Makefile .
51
65
ENTRYPOINT ["poetry" , "run" ]
52
66
53
67
# Copy the http python package and requirements from relevant builder
54
68
FROM base_app as http_app
55
69
COPY --from=http_builder /poetryvenvs /poetryvenvs
56
- COPY http_app ./http_app
57
- CMD exec opentelemetry-instrument uvicorn http_app:create_app --host 0.0.0.0 --port 8000 --factory
70
+ COPY --chown=nonroot:nonroot http_app ./http_app
71
+ # opentelemetry-instrument will spawn a subprocess, therefore we use exec
72
+ # to make sure the app runs on PID 1 and receives correctly system signals
73
+ CMD opentelemetry-instrument uvicorn http_app:create_app --host 0.0.0.0 --port 8000 --factory
58
74
59
75
# Copy the grpc python package and requirements from relevant builder
60
76
FROM base_app as grpc_app
61
77
COPY --from=grpc_builder /poetryvenvs /poetryvenvs
62
- COPY grpc_app ./grpc_app
78
+ COPY --chown=nonroot:nonroot grpc_app ./grpc_app
79
+ # opentelemetry-instrument will spawn a subprocess, therefore we use exec
80
+ # to make sure the app runs on PID 1 and receives correctly system signals
63
81
CMD exec opentelemetry-instrument python3 -m grpc_app
0 commit comments