# Single OCI image bundling the Vue/Vite frontend, the Django/Channels web # process (daphne) and the RQ worker, managed together by supervisord - see # deploy/docker/README.md for why (single-container Proxmox deploy) and how # to run it. Postgres, Redis and S3 stay external (see # deploy/docker/polylan-submitter.env.dist for the full env var list) - this # image carries no infra, just the app. # # Build (from repo root, requires BuildKit/buildx - RUN --mount=type=cache # below is rejected by the legacy builder): # docker buildx build --load -t polylan-submitter . # ---- frontend build ------------------------------------------------------- FROM node:22-alpine AS frontend-builder WORKDIR /app COPY polylan_submitter/package.json polylan_submitter/pnpm-lock.yaml ./ RUN corepack enable && corepack prepare pnpm@9.0.0 --activate \ && pnpm install --frozen-lockfile COPY polylan_submitter/vite.config.ts polylan_submitter/tsconfig*.json ./ COPY polylan_submitter/src ./src COPY polylan_submitter/public ./public RUN pnpm build # ---- python dependencies --------------------------------------------------- FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS python-builder ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy WORKDIR /app COPY pyproject.toml uv.lock ./ # --no-install-project: this pyproject has no [build-system]/package to # install, it only pins the app's dependencies - so just build the venv. RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --frozen --no-dev --no-install-project # ---- runtime ---------------------------------------------------------------- FROM python:3.13-slim AS runtime # tesseract-ocr: shelled out to by pytesseract (submissions/tasks.py, # opus_magnum/utils.py) for OCR'ing Opus Magnum submission GIFs. # libgl1/libglib2.0-0: runtime shared libs opencv-python needs even though # it ships as a wheel. # libpq5: psycopg (plain, not psycopg[binary]/[c]) loads libpq via ctypes. # supervisor/tini: process supervision - see deploy/docker/supervisord.conf. RUN apt-get update && apt-get install -y --no-install-recommends \ tesseract-ocr \ libgl1 \ libglib2.0-0 \ libpq5 \ supervisor \ tini \ && rm -rf /var/lib/apt/lists/* RUN groupadd --system app && useradd --system --gid app --create-home app WORKDIR /app COPY --from=python-builder --chown=app:app /app/.venv /app/.venv ENV PATH="/app/.venv/bin:$PATH" \ PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 \ DJANGO_SETTINGS_MODULE=polylan_submitter.settings COPY --chown=app:app polylan_submitter/ /app/polylan_submitter/ COPY --from=frontend-builder --chown=app:app /app/static_source/vite /app/polylan_submitter/static_source/vite COPY --chown=app:app deploy/docker/entrypoint.sh /app/entrypoint.sh COPY --chown=app:app deploy/docker/supervisord.conf /app/supervisord.conf RUN rm -rf /app/polylan_submitter/node_modules /app/polylan_submitter/settingsLocal.py \ && mkdir -p /app/polylan_submitter/static /app/polylan_submitter/media \ && chown app:app /app/polylan_submitter/static /app/polylan_submitter/media \ && chmod +x /app/entrypoint.sh USER app WORKDIR /app/polylan_submitter EXPOSE 8000 ENTRYPOINT ["tini", "--", "/app/entrypoint.sh"] CMD ["supervisord", "-c", "/app/supervisord.conf", "-n"]