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
2561LABEL org.opencontainers.image.source="https://github.com/aboutcode-org/scancode.io"
2662LABEL org.opencontainers.image.description="ScanCode.io"
@@ -32,10 +68,7 @@ ARG APP_GID=1000
3268
3369ENV APP_NAME=scancodeio
3470ENV APP_USER=app
35- ENV APP_UID=${APP_UID}
36- ENV APP_GID=${APP_GID}
3771ENV 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)
4174ENV 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
81120WORKDIR $APP_DIR
82121USER $APP_USER
83122
84123# Create static/ and workspace/ directories
85124RUN 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