# syntax=docker/dockerfile:1.7 # ===================================================================== # Stage 1 — Frontend (статика для встроенной раздачи) # ===================================================================== FROM node:20-alpine AS frontend-builder WORKDIR /app/frontend RUN npm install -g pnpm@9 # Сначала только манифесты — слой с зависимостями кешируется отдельно. COPY frontend/package.json frontend/pnpm-lock.yaml ./ # "cyberhack" — не публикуемый npm-пакет, а собранный wasm-pack бандл из # отдельного репозитория (Cyberhack), завендоренный прямо сюда (см. # frontend/vendor/README, если появится) — иначе pnpm install не смог бы # разрешить `file:./vendor/cyberhack` в CI, где второй репозиторий не # чекаутится. Должен быть скопирован ДО pnpm install, а не вместе с # остальным `frontend/`, — иначе разрешение зависимости упадёт. COPY frontend/vendor ./vendor RUN pnpm install --frozen-lockfile COPY frontend/ . RUN pnpm build # ===================================================================== # Stage 2 — Cargo Chef (план зависимостей для эффективного кеша слоёв) # ===================================================================== FROM rust:latest AS chef RUN apt-get update \ && apt-get install -y --no-install-recommends pkg-config libssl-dev \ && rm -rf /var/lib/apt/lists/* RUN cargo install cargo-chef --locked WORKDIR /app FROM chef AS planner COPY Cargo.toml Cargo.lock ./ COPY src ./src RUN cargo chef prepare --recipe-path recipe.json # ===================================================================== # Stage 3 — Сборка бэкенда # ===================================================================== FROM chef AS builder # Слой зависимостей: пересобирается только при изменении Cargo.toml/Cargo.lock. COPY --from=planner /app/recipe.json recipe.json RUN cargo chef cook --release --recipe-path recipe.json # Теперь исходники. sqlx работает в offline-режиме — БД при сборке не нужна. ENV SQLX_OFFLINE=true COPY Cargo.toml Cargo.lock ./ COPY src ./src COPY migrations ./migrations RUN cargo build --release --bin netrunner-control-plane # ===================================================================== # Stage 4 — Минимальный рантайм-образ # ===================================================================== FROM debian:bookworm-slim AS runtime RUN apt-get update \ && apt-get install -y --no-install-recommends ca-certificates libssl3 curl \ && rm -rf /var/lib/apt/lists/* \ && useradd -r -u 10001 -m -d /app netrunner WORKDIR /app COPY --from=builder /app/target/release/netrunner-control-plane . COPY --from=frontend-builder /app/frontend/dist ./frontend/dist COPY migrations ./migrations COPY templates ./templates RUN chown -R netrunner:netrunner /app USER netrunner ENV FRONTEND_DIR=/app/frontend/dist \ PORT=8080 EXPOSE 8080 HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ CMD curl -fsS "http://localhost:${PORT}/health" || exit 1 CMD ["./netrunner-control-plane"]