-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathDockerfile
More file actions
153 lines (128 loc) · 6.03 KB
/
Dockerfile
File metadata and controls
153 lines (128 loc) · 6.03 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
148
149
150
151
152
153
# ------------------------------------------------------------
# 1️⃣ Builder stage – builds the virtual environment
# ------------------------------------------------------------
FROM python:3.11.3 AS build
# Build argument to select dependency group (wvnet or uat)
ARG DEPENDENCY_GROUP=wvnet
ENV POETRY_NO_INTERACTION=1 \
POETRY_VIRTUALENVS_IN_PROJECT=1 \
POETRY_VIRTUALENVS_CREATE=1 \
POETRY_CACHE_DIR=/tmp/poetry_cache
WORKDIR /app
COPY pyproject.toml poetry.lock ./
RUN pip install poetry==2.1.4 \
&& pip install pipdeptree \
&& set -ex \
&& BUILD_DEPS=" \
build-essential \
libpcre3-dev \
libpq-dev \
default-libmysqlclient-dev \
pkg-config \
" \
&& apt update \
&& apt upgrade -y \
&& apt install -y --no-install-recommends $BUILD_DEPS \
&& touch README.md \
&& poetry install --with ${DEPENDENCY_GROUP} --no-root \
&& rm -rf $POETRY_CACHE_DIR \
&& pipdeptree -fl --exclude poetry --exclude pipdeptree --python /app/.venv/bin/python > requirements.txt
# ------------------------------------------------------------
# Test stage - contains dev dependencies for testing
# Tests are now run in Jenkins before the build, not during Docker build
# ------------------------------------------------------------
FROM build AS test
# Install dev dependencies for testing
RUN poetry install --with dev --no-root
COPY ./ ./
# Test stage is ready for running tests in Jenkins
# Tests will be executed by Jenkins using: /app/.venv/bin/pytest ...
# ------------------------------------------------------------
# 2️⃣ Runtime stage for MAIN branch (production)
# ------------------------------------------------------------
FROM python:3.11-slim AS runtime-production
WORKDIR /app
# Copy your application code to the container
COPY --exclude=./tests ./ ./
# Copy virtual env from build stage
COPY --from=build /app/requirements.txt ./
RUN useradd -rm -d /home/ubuntu -s /bin/bash -g root -G sudo -u 1000 ubuntu \
&& apt update \
&& apt upgrade -y \
&& apt install openssh-client wget -y \
&& pip install paramiko==3.5.1 pysftp \
&& rm ./poetry.toml \
&& rm ./poetry.lock \
&& rm ./pyproject.toml \
&& rm ./pytest.ini \
&& rm ./.coveragerc \
&& mkdir /wsgi \
&& mv ./src/parts_webapi/wsgi.py /wsgi/wsgi.py \
&& mkdir /scripts \
&& cd /scripts \
&& wget https://raw.githubusercontent.com/bduke-dev/scripts/main/delete_remote_files.py \
&& wget https://raw.githubusercontent.com/bduke-dev/scripts/main/upload_directory.py
# ------------------------------------------------------------
# 2️⃣ Runtime stage for UAT branch
# ------------------------------------------------------------
FROM python:3.11-slim AS runtime-uat
# ── Expose the HTTP port that uWSGI will listen on ────────────────────────
EXPOSE 9090
# ── Environment variables ───────────────────────────────────────────────────
ENV PYTHONUNBUFFERED=1 \
VIRTUAL_ENV=/app/.venv \
PATH="/app/.venv/bin:${PATH}" \
PYTHONPATH=/app/src \
UWSGI_WSGI_FILE=src/parts_webapi/wsgi.py \
UWSGI_HTTP=:9090 \
UWSGI_MASTER=1 \
UWSGI_HTTP_AUTO_CHUNKED=1 \
UWSGI_HTTP_KEEPALIVE=1 \
UWSGI_LAZY_APPS=1 \
UWSGI_WSGI_ENV_BEHAVIOR=holy \
UWSGI_WORKERS=2 \
UWSGI_THREADS=4 \
LIB_SSL=libssl1.1_1.1.1f-1ubuntu2.24_amd64.deb
# ── Runtime dependencies (no build‑deps) ─────────────────────────────────────
RUN RUN_DEPS=" \
default-mysql-client \
libxml2 \
cron \
curl \
gosu \
" \
&& mkdir -p /usr/share/man/man{1..8} \
&& apt update \
&& apt upgrade -y \
&& apt install -y --no-install-recommends $RUN_DEPS \
&& rm -rf /var/lib/apt/lists/* \
&& curl -fsSL https://nz2.archive.ubuntu.com/ubuntu/pool/main/o/openssl/${LIB_SSL} -o ${LIB_SSL} \
&& dpkg -i ${LIB_SSL} \
&& rm ${LIB_SSL}
# ── Working directory ───────────────────────────────────────────────────────
WORKDIR /app
# ── Pull the virtual‑env built in the previous stage ───────────────────────
COPY --from=build ${VIRTUAL_ENV} ${VIRTUAL_ENV}
# ── Copy application source code ───────────────────────────────────────────
COPY --exclude=./tests ./ /app
# ── Create the non‑privileged user (UID/GID 1000) ────────────────────────
RUN groupadd -g 1000 appuser && \
useradd -m -u 1000 -g appuser -s /bin/bash appuser
# ── Set up the crontab (runs as root) ─────────────────────────────────────
RUN mv ./crontab /etc/cron.d/myjob \
&& chmod 0644 /etc/cron.d/myjob \
&& crontab /etc/cron.d/myjob \
&& touch /var/log/cron.log \
&& chmod 666 /var/log/cron.log # writable for any user (including appuser)
# ── Health‑check ───────────────────────────────────────────────────────────
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD sh -c '\
pid_file="/var/run/crond.pid"; \
[ -f "$pid_file" ] && \
pid=$(cat "$pid_file") && \
[ -d "/proc/$pid" ] && exit 0; \
exit 1'
# ── ENTRYPOINT / CMD ───────────────────────────────────────────────────────
# • `cron -f` stays in the foreground (runs as root)
# • `gosu appuser uwsgi …` drops to the non‑privileged user **only** for uWSGI
CMD ["sh", "-c", "cron -f & exec gosu appuser uwsgi --show-config"]