forked from Kegbot/kegbot-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile
More file actions
128 lines (107 loc) · 4.75 KB
/
Copy pathDockerfile
File metadata and controls
128 lines (107 loc) · 4.75 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
# ── Stage 1: build ────────────────────────────────────────────────────────────
# python:3.10-bullseye inherits buildpack-deps which already includes gcc,
# default-libmysqlclient-dev, libpq-dev, libffi-dev, libssl-dev, zlib1g-dev,
# curl, and other common build tools — no need to install them again.
FROM python:3.10-bullseye AS builder
RUN mkdir /app
WORKDIR /app
ENV PIP_NO_CACHE_DIR=1
# Pillow-specific build headers not covered by buildpack-deps.
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \
libfreetype6-dev \
libfribidi-dev \
libharfbuzz-dev \
libjpeg-dev \
liblcms2-dev \
libopenjp2-7-dev \
libtiff-dev \
libwebp-dev \
&& rm -rf /var/lib/apt/lists/*
RUN python -m pip install -U pip && pip install poetry && rm -rf /root/.cache
# Resolve and install production-only Python dependencies (no pytest, sphinx, etc.).
COPY pyproject.toml poetry.lock ./
ADD pykeg/__init__.py ./pykeg/
RUN poetry config virtualenvs.create false && poetry lock && poetry install --without dev -n
# ── Stage: test ───────────────────────────────────────────────────────────────
# Layers the dev dependencies (pytest, pytest-cov, etc.) on top of the builder so
# the suite runs against the same compiled extensions as production. This stage is
# never part of the runtime image — `docker build` defaults to the final stage, and
# docker-compose.test.yml builds it explicitly with `target: test`.
FROM builder AS test
# Install only the test tooling on top of the prod deps already present from the
# builder. We deliberately do NOT re-run `poetry install`: the builder's
# `poetry install` pinned `packaging` to the app's version, which is too old for
# poetry 2.x to run again ("No module named 'packaging.metadata'"). pip-installing
# the handful of test packages directly is both simpler and faster, and skips the
# docs/lint tooling (sphinx, black, flake8) that the suite doesn't need.
RUN pip install --no-cache-dir \
pytest \
pytest-django \
pytest-cov \
pytest-asyncio \
requests-mock \
vcrpy
# Application source and test data. Deps are already installed above so changes
# here don't bust the dependency layer cache.
ADD pykeg ./pykeg
ADD testdata ./testdata
COPY setup.cfg ./
# whitenoise inspects STATIC_ROOT on startup and warns once per test module if it
# is missing. We don't collectstatic in the test image, so create an empty dir to
# keep the warning out of the test output.
RUN mkdir -p staticfiles
ENV KEGBOT_ENV=test \
KEGBOT_SECRET_KEY=test-secret-key \
PYTHONDONTWRITEBYTECODE=1
# Default to the full suite with coverage; override the command to scope it down.
CMD ["pytest", "--cov=pykeg", "--cov-report=term-missing"]
# ── Stage 2: runtime ──────────────────────────────────────────────────────────
FROM python:3.10-slim-bullseye AS runtime
RUN mkdir /app
WORKDIR /app
ENV SHELL=/bin/sh \
PIP_NO_CACHE_DIR=1 \
KEGBOT_DATA_DIR=/kegbot-data \
KEGBOT_IN_DOCKER=True \
KEGBOT_ENV=debug
# Runtime shared libraries needed by compiled Python extensions.
# No -dev headers, no gcc, no build toolchain.
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \
libffi7 \
libfreetype6 \
libfribidi0 \
libharfbuzz0b \
libjpeg62-turbo \
liblcms2-2 \
libopenjp2-7 \
libtiff5 \
libwebp6 \
libssl1.1 \
libmariadb3 \
libpq5 \
netcat-openbsd \
&& rm -rf /var/lib/apt/lists/*
# Copy installed Python packages and console scripts from the builder.
COPY --from=builder /usr/local/lib/python3.10/site-packages/ /usr/local/lib/python3.10/site-packages/
COPY --from=builder /usr/local/bin/ /usr/local/bin/
# Install the application.
ADD bin /usr/local/sbin/
ADD pykeg ./pykeg
# Collect static files. Dummy env values — no real DB/Redis needed at build time.
RUN DATABASE_URL=mysql:// \
REDIS_URL=redis:// \
KEGBOT_SECRET_KEY=changeme \
kegbot collectstatic --noinput -v 0
# Embed build metadata.
ARG GIT_SHORT_SHA="unknown"
ARG VERSION="unknown"
ARG BUILD_DATE="unknown"
RUN echo "GIT_SHORT_SHA=${GIT_SHORT_SHA}\nVERSION=${VERSION}\nBUILD_DATE=${BUILD_DATE}" > /etc/kegbot-version
COPY docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
VOLUME ["/kegbot-data"]
EXPOSE 8000
ENTRYPOINT ["/usr/local/sbin/kegbot"]
CMD ["run_server"]