# =================================================================== # Stage 1: Build the frontend # =================================================================== FROM node:22-alpine AS frontend-builder WORKDIR /app # Copy package files first for dependency caching COPY frontend/package.json frontend/package-lock.json ./ RUN npm ci # Copy source and build COPY frontend/ ./ RUN npm run build # =================================================================== # Stage 2: Build the Rust backend # =================================================================== FROM rust:1.85-bookworm AS builder WORKDIR /app # Copy manifests first for dependency caching COPY backend/Cargo.toml backend/Cargo.lock ./ # Create a dummy main.rs to build dependencies RUN mkdir src && echo "fn main() {}" > src/main.rs RUN cargo build --release RUN rm -rf src # Copy the actual source code and migrations COPY backend/src/ src/ COPY backend/migrations/ migrations/ # Set sqlx offline mode (no live DB needed during build) ENV SQLX_OFFLINE=true # Touch main.rs so cargo knows the source changed RUN touch src/main.rs RUN cargo build --release # =================================================================== # Stage 3: Minimal runtime image # =================================================================== FROM debian:bookworm-slim AS runtime # Install only what the binary needs at runtime RUN apt-get update \ && apt-get install -y --no-install-recommends \ ca-certificates \ libssl3 \ curl \ && rm -rf /var/lib/apt/lists/* # Create non-root user RUN groupadd --system appuser \ && useradd --system --gid appuser --home-dir /app --no-create-home --shell /usr/sbin/nologin appuser WORKDIR /app # Copy backend binary COPY --from=builder /app/target/release/ai-synth-backend ./ai-synth-backend # Copy migrations (run at startup) COPY --from=builder /app/migrations/ ./migrations/ # Copy built frontend COPY --from=frontend-builder /app/dist/ ./static/ # Set ownership RUN chown -R appuser:appuser /app USER appuser ENV PORT=8080 EXPOSE 8080 HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ CMD curl -f http://localhost:8080/api/v1/health || exit 1 ENTRYPOINT ["./ai-synth-backend"] CMD ["serve"]