diff --git a/.dockerignore b/.dockerignore index 0715d0b..a75967b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,10 +1,17 @@ **/node_modules -**/dist -**/build **/.dart_tool **/coverage -.git **/*.log +.git +.github +backend/dist +# Flutter platform scaffolding / caches — the build/web bundle IS needed. +client/app/android +client/app/ios +client/app/linux +client/app/macos +client/app/windows +client/app/.dart_tool # Secrets: passed at runtime via env_file / bind mount, never baked in. backend/.env backend/serviceAccount.json diff --git a/Dockerfile b/Dockerfile index a8261e9..c90356a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,11 @@ # syntax=docker/dockerfile:1 +# +# The Flutter web bundle is built on the HOST (it needs a ~2.8 GB SDK image +# otherwise). Before `docker compose build`, run: +# (cd client/app && flutter build web --release) +# This Dockerfile just copies client/app/build/web into the runtime image. -# --- 1. Flutter web build ------------------------------------------------- -FROM ghcr.io/cirruslabs/flutter:stable AS web -WORKDIR /src -COPY client/app/pubspec.yaml client/app/pubspec.lock ./ -RUN flutter pub get -COPY client/app/ ./ -RUN flutter build web --release - -# --- 2. Backend build -------------------------------------------------------- +# --- 1. Backend build --------------------------------------------------------- FROM node:20-bookworm-slim AS api-build WORKDIR /src COPY backend/package.json backend/package-lock.json ./ @@ -16,7 +13,7 @@ RUN npm ci COPY backend/ ./ RUN npx prisma generate && npm run build -# --- 3. Runtime ------------------------------------------------------------ +# --- 2. Runtime ------------------------------------------------------------- FROM node:20-bookworm-slim AS runtime ENV NODE_ENV=production WORKDIR /app @@ -26,8 +23,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends openssl \ COPY --from=api-build /src/node_modules ./node_modules COPY --from=api-build /src/dist ./dist COPY --from=api-build /src/prisma ./prisma -# The Flutter web build; app.module reads WEB_CLIENT_DIR. -COPY --from=web /src/build/web ./web +# Pre-built Flutter web bundle from the host; app.module reads WEB_CLIENT_DIR. +COPY client/app/build/web ./web ENV WEB_CLIENT_DIR=/app/web EXPOSE 3000 # Apply pending migrations, then boot. diff --git a/README.md b/README.md index 2229e9a..778fabe 100644 --- a/README.md +++ b/README.md @@ -8,17 +8,22 @@ for the full architecture and phased roadmap. ## Run with Docker ```bash -cp backend/.env.example backend/.env # fill in the secrets -# put the Firebase service account at backend/serviceAccount.json (optional; push) +cp backend/.env.example backend/.env # fill in the secrets +# optional (push): put the Firebase service account at backend/serviceAccount.json +(cd client/app && flutter build web --release) # host build — see note below docker compose up --build ``` -`docker-compose.yml` starts PostgreSQL 16 and one `api` container (multi-stage -`Dockerfile`: Flutter web build → NestJS build → slim runtime). The container -runs `prisma migrate deploy` on start and serves the whole app — Flutter web +`docker-compose.yml` starts PostgreSQL 16 and one `api` container (2-stage +`Dockerfile`: NestJS build → slim runtime). The container runs +`prisma migrate deploy` on start and serves the whole app — Flutter web client + REST API — on . Requires Docker Compose v2. -Secrets are read from `backend/.env` and the service-account JSON is bind- -mounted read-only; neither is baked into the image. + +The Flutter web bundle is built **on the host** and copied in (a Flutter +builder stage would pull a ~2.8 GB SDK image). So `flutter build web` must +run before `docker compose build`. Secrets come from `backend/.env` +(unquoted, Compose v2 strips quotes) and the service-account JSON is +bind-mounted read-only — neither is baked into the image. ## Structure