Skip to content

Commit 52b248e

Browse files
authored
feat!: convert Dockerfile to multi-stage build (#2139)
Signed-off-by: tdruez <tdruez@aboutcode.org>
1 parent c2bfd15 commit 52b248e

1 file changed

Lines changed: 46 additions & 23 deletions

File tree

Dockerfile

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,43 @@
2020
# ScanCode.io is a free software code scanning tool from nexB Inc. and others.
2121
# Visit https://github.com/aboutcode-org/scancode.io for support and download.
2222

23-
FROM python:3.13-slim
23+
# ============================================
24+
# Stage 1: Build stage
25+
# ============================================
26+
27+
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS builder
28+
29+
# Compile bytecode for faster startup
30+
ENV UV_COMPILE_BYTECODE=1
31+
# Copy files instead of linking (cache and target are on different filesystems)
32+
ENV UV_LINK_MODE=copy
33+
# Skip dev dependencies
34+
ENV UV_NO_DEV=1
35+
# Use the system Python, don't download one
36+
ENV UV_PYTHON_DOWNLOADS=0
37+
# Set uv cache directory for BuildKit cache mounts
38+
ENV UV_CACHE_DIR=/root/.cache/uv
39+
40+
ENV APP_NAME=scancodeio
41+
ENV APP_DIR=/opt/$APP_NAME
42+
WORKDIR $APP_DIR
43+
44+
# Only re-runs when uv.lock changes
45+
RUN --mount=type=cache,target=/root/.cache/uv \
46+
--mount=type=bind,source=uv.lock,target=uv.lock \
47+
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
48+
uv sync --frozen --no-install-project
49+
50+
# Only re-runs when local code changes
51+
COPY . $APP_DIR
52+
RUN --mount=type=cache,target=/root/.cache/uv \
53+
uv sync --frozen
54+
55+
# ============================================
56+
# Stage 2: Production stage
57+
# ============================================
58+
59+
FROM python:3.13-slim-bookworm
2460

2561
LABEL org.opencontainers.image.source="https://github.com/aboutcode-org/scancode.io"
2662
LABEL org.opencontainers.image.description="ScanCode.io"
@@ -32,10 +68,7 @@ ARG APP_GID=1000
3268

3369
ENV APP_NAME=scancodeio
3470
ENV APP_USER=app
35-
ENV APP_UID=${APP_UID}
36-
ENV APP_GID=${APP_GID}
3771
ENV APP_DIR=/opt/$APP_NAME
38-
ENV VENV_LOCATION=/opt/$APP_NAME/.venv
3972

4073
# Force Python unbuffered stdout and stderr (they are flushed to terminal immediately)
4174
ENV PYTHONUNBUFFERED=1
@@ -52,8 +85,8 @@ RUN apt-get update \
5285
bzip2 \
5386
xz-utils \
5487
zlib1g \
55-
libxml2-dev \
56-
libxslt1-dev \
88+
libxml2 \
89+
libxslt1.1 \
5790
libgomp1 \
5891
libsqlite3-0 \
5992
libgcrypt20 \
@@ -77,25 +110,15 @@ RUN groupadd --gid $APP_GID --system $APP_USER \
77110
&& mkdir -p /var/$APP_NAME \
78111
&& chown $APP_USER:$APP_USER /var/$APP_NAME
79112

80-
# Setup the work directory and the user as APP_USER for the remaining stages
113+
# Copy the application from the builder
114+
COPY --from=builder --chown=$APP_USER:$APP_USER $APP_DIR $APP_DIR
115+
116+
# Place executables in the environment at the front of the path
117+
ENV PATH="$APP_DIR/.venv/bin:$PATH"
118+
119+
# Setup the $APP_DIR as work directory and the user as APP_USER for the remaining stages
81120
WORKDIR $APP_DIR
82121
USER $APP_USER
83122

84123
# Create static/ and workspace/ directories
85124
RUN mkdir -p /var/$APP_NAME/static/ /var/$APP_NAME/workspace/
86-
87-
# Create the virtualenv
88-
RUN python -m venv $VENV_LOCATION
89-
# Enable the virtualenv, similar effect as "source activate"
90-
ENV PATH=$VENV_LOCATION/bin:$PATH
91-
92-
# Install uv by copying the binary from the official distroless Docker image
93-
COPY --from=ghcr.io/astral-sh/uv:0.11.2 /uv /uvx /bin/
94-
95-
# Only re-runs when uv.lock changes
96-
COPY --chown=$APP_USER:$APP_USER pyproject.toml uv.lock $APP_DIR/
97-
RUN uv sync --frozen --no-install-project
98-
99-
# Only re-runs when local code changes
100-
COPY --chown=$APP_USER:$APP_USER . $APP_DIR
101-
RUN uv sync --frozen

0 commit comments

Comments
 (0)