-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile
More file actions
147 lines (106 loc) · 3.67 KB
/
Dockerfile
File metadata and controls
147 lines (106 loc) · 3.67 KB
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# syntax=docker/dockerfile:1
ARG PYTHON_VERSION
ARG DIR_APP="/app"
ARG DIR_CACHE="/var/cache/app"
ARG GROUP_ID=9999
ARG USER_ID=9999
ARG USERNAME=ex
# ~~~~ Target: build-task ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# purpose: to build `task` app: see https://taskfile.dev
FROM golang:1.20.4-alpine3.18 AS build-task
ENV GOBIN=/app/bin
WORKDIR /app
RUN go install github.com/go-task/task/v3/cmd/task@latest
# ~~~~ Target: base ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# purpose: build system packages, Python packages, venv
FROM python:${PYTHON_VERSION}-alpine3.18 AS base
LABEL description="Webapp for Example: Clean Architecture"
LABEL org.opencontainers.image.authors="Alexander Sidorov <alexander@sidorov.dev>"
# install system packages
RUN apk update && apk add --no-interactive --upgrade \
bash \
curl \
gcc \
libffi-dev \
musl-dev
# install system Python apps
ARG PIP_VERSION
RUN pip install "pip==${PIP_VERSION}"
ARG POETRY_VERSION
RUN pip install "poetry==${POETRY_VERSION}"
# create non-root user and its dirs
ARG DIR_APP
ARG DIR_CACHE
ARG GROUP_ID
ARG USER_ID
ARG USERNAME
RUN addgroup --gid ${GROUP_ID} --system ${USERNAME} \
&& adduser \
--disabled-password \
--home="/home/${USERNAME}" \
--ingroup=${USERNAME} \
--shell=/bin/bash \
--system \
--uid=${USER_ID} \
${USERNAME} \
&& install --owner ${USERNAME} --group ${USERNAME} --directory "${DIR_APP}" \
&& install --owner ${USERNAME} --group ${USERNAME} --directory "${DIR_CACHE}"
WORKDIR "${DIR_APP}"
USER ${USERNAME}
# create virtual env using Poetry
COPY ./pyproject.toml ./poetry.lock ./
ENV POETRY_NO_INTERACTION=1
ENV POETRY_VIRTUALENVS_ALWAYS_COPY=false
ENV POETRY_VIRTUALENVS_CREATE=true
ENV POETRY_VIRTUALENVS_IN_PROJECT=false
ENV POETRY_VIRTUALENVS_PATH="${DIR_CACHE}"
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV PYTHONUTF8=1
RUN poetry env use "${PYTHON_VERSION}" \
&& poetry env info > "${DIR_CACHE}/.poetry-env-info.txt" \
&& poetry install --without dev --no-root
# ~~~~ Target: production ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# purpose: the image itself
FROM python:${PYTHON_VERSION}-alpine3.18 AS production
ARG DIR_APP
ARG DIR_CACHE
ARG GROUP_ID
ARG USER_ID
ARG USERNAME
# create non-root user and its dirs
RUN addgroup --gid ${GROUP_ID} --system ${USERNAME} \
&& adduser \
--disabled-password \
--home="/home/${USERNAME}" \
--ingroup=${USERNAME} \
--shell=/bin/bash \
--system \
--uid=${USER_ID} \
${USERNAME} \
&& install --owner ${USERNAME} --group ${USERNAME} --directory "${DIR_APP}" \
&& install --owner ${USERNAME} --group ${USERNAME} --directory "${DIR_APP}/.local" \
&& install --owner ${USERNAME} --group ${USERNAME} --directory "${DIR_CACHE}"
# copy stuff from previous stages
COPY --from=base "${DIR_CACHE}" "${DIR_CACHE}"
COPY --from=base /bin/bash /bin/bash
COPY --from=base /usr/bin/curl /usr/bin/curl
COPY --from=base /usr/local/bin/poetry /usr/local/bin/poetry
COPY --from=base /usr/local/lib/python3.11/site-packages/ /usr/local/lib/python3.11/site-packages/
COPY --from=build-task /app/bin/task /usr/bin/task
WORKDIR "${DIR_APP}"
USER ${USERNAME}
COPY . .
# let Poetry know about previously built venv
ENV POETRY_NO_INTERACTION=1
ENV POETRY_VIRTUALENVS_ALWAYS_COPY=false
ENV POETRY_VIRTUALENVS_CREATE=true
ENV POETRY_VIRTUALENVS_IN_PROJECT=false
ENV POETRY_VIRTUALENVS_PATH="${DIR_CACHE}"
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV PYTHONUTF8=1
# integrate static stuff into this image
RUN task collect-static
# fixme: depends on Gunicorn settings, but I don't care
EXPOSE 80