Files
kca/server/Dockerfile

96 lines
3.5 KiB
Docker

# syntax=docker/dockerfile:1
# Multi-stage production image for KCA (kaya backend + Sycamore/WASM frontend).
# The build context is the repository root (see ../docker-compose.yml).
# --- Frontend --------------------------------------------------------------
FROM rust:1-slim AS web-builder
ARG TRUNK_VERSION=0.21.14
RUN sed -i 's|http://deb.debian.org|https://deb.debian.org|g' \
/etc/apt/sources.list.d/debian.sources 2>/dev/null || true \
&& apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates \
&& rm -rf /var/lib/apt/lists/*
RUN curl -sSfL \
"https://github.com/trunk-rs/trunk/releases/download/v${TRUNK_VERSION}/trunk-x86_64-unknown-linux-gnu.tar.gz" \
| tar -xz -C /usr/local/bin \
&& rustup target add wasm32-unknown-unknown
WORKDIR /web
COPY web/Cargo.toml web/Cargo.lock ./
COPY web/index.html web/style.css web/theme.css web/Trunk.toml ./
COPY web/vendor ./vendor
COPY web/pwa ./pwa
COPY web/src ./src
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/web/target \
trunk build --release --public-url /static/
# --- Backend ---------------------------------------------------------------
FROM python:3.12-slim-trixie AS builder
COPY --from=ghcr.io/astral-sh/uv:0.13.1 /uv /uvx /bin/
RUN sed -i 's|http://deb.debian.org|https://deb.debian.org|g' \
/etc/apt/sources.list.d/debian.sources 2>/dev/null || true \
&& apt-get update \
&& apt-get install -y --no-install-recommends build-essential git \
&& rm -rf /var/lib/apt/lists/*
RUN git config --global --add safe.directory /repo
ENV UV_PYTHON_DOWNLOADS=0 \
UV_PROJECT_ENVIRONMENT=/opt/venv \
UV_LINK_MODE=copy
WORKDIR /repo/server
COPY server/uv.lock server/pyproject.toml ./
COPY server/packages/kca-core/pyproject.toml packages/kca-core/
COPY server/packages/kca-app/pyproject.toml packages/kca-app/
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-install-workspace --package kca-app --extra otel --no-dev
COPY server/packages/ ./packages/
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --locked --no-editable --package kca-app --extra otel --no-dev \
--reinstall-package kca-core --reinstall-package kca-app
COPY server/migrations ./migrations
# --- Runtime ---------------------------------------------------------------
FROM python:3.12-slim-trixie
RUN sed -i 's|http://deb.debian.org|https://deb.debian.org|g' \
/etc/apt/sources.list.d/debian.sources 2>/dev/null || true \
&& apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates tzdata libssl3 \
&& rm -rf /var/lib/apt/lists/* \
&& groupadd --system app \
&& useradd --system --gid app --no-create-home --shell /usr/sbin/nologin app \
&& install -d -o app -g app /data
COPY --from=builder /opt/venv /opt/venv
COPY --from=builder /repo/server/migrations /app/migrations
COPY --from=builder /repo/server/pyproject.toml /app/pyproject.toml
COPY --from=web-builder /web/dist /app/web/dist
ENV PATH="/opt/venv/bin:$PATH" \
PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
GRANIAN_HOST=0.0.0.0 \
GRANIAN_PORT=8080 \
GRANIAN_INTERFACE=rsgi \
GRANIAN_STATIC_PATH_ROUTE="/static" \
GRANIAN_STATIC_PATH_MOUNT="/app/web/dist" \
GRANIAN_STATIC_PATH_DIR_TO_FILE=index.html \
STATIC_DIR=/app/web/dist
USER app
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s \
CMD python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/api/health', timeout=2).read()" || exit 1
CMD ["granian", "kca.app:app"]