Skip to content

Commit 5579a51

Browse files
committed
refactor(docker): slim multi-stage build, drop image size by ~58%
Rework the Dockerfile into a real two-stage build: - builder stage: python:3.13-slim + build toolchain, installs all requirements into an isolated venv at /opt/venv - dev stage: python:3.13-slim with only runtime packages (postgresql-client) and the interactive tooling the dev shell needs (fish, neovim, less, ack, iputils-ping), copying the venv from the builder The build toolchain (build-essential, gcc) no longer ships in the final image, cutting it from ~1.69GB to ~715MB. Other fixes: - drop the stray `aws` package from the install line (junk PyPI package; boto3 already provides the AWS SDK) - stop reinstalling ruff via pip -U (it is already pinned in dev.txt) - switch ADD to COPY for the requirements files - add apt cache mounts for /var/lib/apt/lists with sharing=locked - add a .dockerignore to shrink the build context and keep .env/secrets out Add a .dockerignore covering VCS, Python caches, local databases, env files and tooling output.
1 parent 087dac5 commit 5579a51

2 files changed

Lines changed: 86 additions & 14 deletions

File tree

.dockerignore

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Version control
2+
.git
3+
.gitignore
4+
5+
# Python caches and virtualenvs
6+
__pycache__/
7+
*.py[cod]
8+
*.egg-info/
9+
.eggs/
10+
.pytest_cache/
11+
.ruff_cache/
12+
.mypy_cache/
13+
.coverage
14+
htmlcov/
15+
pythonie-venv/
16+
.venv/
17+
venv/
18+
19+
# Local databases and media
20+
*.sqlite3
21+
pythonie/db.sqlite3
22+
media/
23+
24+
# Secrets and local env
25+
.env
26+
.envrc
27+
*.env
28+
29+
# Editor / OS noise
30+
.vscode/
31+
.idea/
32+
.DS_Store
33+
34+
# Worktrees and tooling output
35+
.claude/
36+
graphify-out/
37+
38+
# Docs and CI not needed in the build context
39+
*.md
40+
.github/

Dockerfile

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,52 @@
11
# syntax=docker/dockerfile:1.21.0
2-
FROM python:3.13 AS compile-stage
3-
RUN --mount=type=cache,target=/var/cache/apt \
4-
apt update && \
5-
apt install -y --no-install-recommends \
6-
build-essential gcc neovim fish less iputils-ping postgresql-client \
7-
ack
8-
ADD requirements/main.txt \
9-
requirements/dev.txt \
10-
requirements/production.txt \
11-
./requirements/
2+
3+
# ---- builder: compile and install Python deps into an isolated venv ----
4+
FROM python:3.13-slim AS builder
5+
6+
ENV UV_LINK_MODE=copy \
7+
PIP_DISABLE_PIP_VERSION_CHECK=1
8+
9+
# build-essential/gcc are only needed to build wheels that lack a prebuilt one.
10+
# They live in this stage only and never reach the final image.
11+
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
12+
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
13+
apt-get update && \
14+
apt-get install -y --no-install-recommends \
15+
build-essential gcc
16+
17+
RUN --mount=type=cache,target=/root/.cache \
18+
pip install -U pip uv
19+
20+
COPY requirements/main.txt \
21+
requirements/dev.txt \
22+
requirements/production.txt \
23+
./requirements/
24+
25+
# Install everything into a self-contained venv at /opt/venv so the final
26+
# stage can copy it without dragging in the build toolchain.
1227
RUN --mount=type=cache,target=/root/.cache \
13-
pip install -U pip uv ruff && \
14-
python -m uv pip install \
28+
uv venv /opt/venv && \
29+
uv pip install --python /opt/venv \
1530
-r requirements/main.txt \
1631
-r requirements/dev.txt \
17-
-r requirements/production.txt aws
32+
-r requirements/production.txt
33+
34+
# ---- dev: lean runtime image with interactive tooling (used by web + test) ----
35+
FROM python:3.13-slim AS dev
36+
37+
ENV PATH="/opt/venv/bin:$PATH" \
38+
PYTHONUNBUFFERED=1 \
39+
PYTHONDONTWRITEBYTECODE=1
40+
41+
# Runtime-only system packages: the postgres client for psql/pg_dump plus the
42+
# interactive tooling the dev shell relies on (compose runs `fish`).
43+
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
44+
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
45+
apt-get update && \
46+
apt-get install -y --no-install-recommends \
47+
postgresql-client \
48+
fish neovim less ack iputils-ping
1849

19-
FROM compile-stage AS tests-stage
50+
COPY --from=builder /opt/venv /opt/venv
2051

52+
WORKDIR /app

0 commit comments

Comments
 (0)