46 lines
1.9 KiB
Docker
46 lines
1.9 KiB
Docker
# ─── Этап 1: сборка SPA ───────────────────────────────────────────────────────
|
|
FROM node:20-bookworm-slim AS frontend
|
|
WORKDIR /app/frontend
|
|
|
|
# Сначала зависимости (кеш слоёв). Используем lock-файл, если он есть.
|
|
COPY frontend/package*.json ./
|
|
RUN npm install --no-audit --no-fund
|
|
|
|
COPY frontend/ ./
|
|
# Типы schema.d.ts уже в репозитории — бэкенд для сборки не нужен.
|
|
RUN npm run build
|
|
|
|
|
|
# ─── Этап 2: рантайм FastAPI (ARM64-совместимый glibc-образ) ──────────────────
|
|
FROM python:3.12-slim-bookworm AS runtime
|
|
# Контейнер — всегда production. БД/загрузки выбираются по APP_ENV (см. config.py):
|
|
# prod → /data на томе. SPA отдаётся из /app/static.
|
|
ENV PYTHONUNBUFFERED=1 \
|
|
PYTHONDONTWRITEBYTECODE=1 \
|
|
APP_ENV=production \
|
|
STATIC_DIR=/app/static
|
|
|
|
# tini — корректная обработка сигналов (чек-пойнт WAL при остановке).
|
|
RUN apt-get update \
|
|
&& apt-get install -y --no-install-recommends tini \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
WORKDIR /app
|
|
|
|
COPY backend/requirements.txt ./requirements.txt
|
|
RUN pip install --no-cache-dir -r requirements.txt
|
|
|
|
COPY backend/ /app/
|
|
COPY --from=frontend /app/frontend/dist /app/static
|
|
|
|
# Непривилегированный пользователь + том данных + исполняемый entrypoint (LF).
|
|
RUN sed -i 's/\r$//' /app/entrypoint.sh \
|
|
&& chmod +x /app/entrypoint.sh \
|
|
&& useradd --create-home --uid 10001 appuser \
|
|
&& mkdir -p /data/uploads /data/achievements \
|
|
&& chown -R appuser:appuser /app /data
|
|
USER appuser
|
|
|
|
EXPOSE 8000
|
|
ENTRYPOINT ["/usr/bin/tini", "--", "/app/entrypoint.sh"]
|