From b6136b0a656989054f46c23410a377c4150ab80d Mon Sep 17 00:00:00 2001 From: SennayT Date: Fri, 5 Jun 2026 11:28:33 +0000 Subject: [PATCH] modify nextjs deployment --- DEPLOYMENT.md | 40 +++++++++++- .../backoffice/next.config.js | 3 +- apps/edr-passenger-web/portal/next.config.js | 1 - checkpoint.md | 31 ++++++++- docker-compose.yaml | 18 ++--- .../docker/Dockerfile.passenger-web | 65 +++++++++++++++++++ 6 files changed, 144 insertions(+), 14 deletions(-) create mode 100644 infrastructure/docker/Dockerfile.passenger-web diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 00ca421d1..2279ac45c 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -61,11 +61,11 @@ The sync script validates this and fails if missing. ### Build env files (optional) -Used for build-time variables (example: Vite API URLs), with `export` syntax: +Used for build-time variables (example: API URLs for Vite/Next.js), with `export` syntax: ```bash export FREIGHT_VITE_API_URL=https://freight-api.example.com/api -export PASSENGER_VITE_API_URL=https://passenger-api.example.com +export PASSENGER_NEXT_PUBLIC_API_URL=https://passenger-api.example.com ``` These are injected into `GITHUB_ENV` during workflow execution. @@ -83,6 +83,42 @@ These are injected into `GITHUB_ENV` during workflow execution. `scripts/deploy/sync-env-from-server.sh` extracts `PORT` from each synced `.env` and exports the corresponding `*_PORT` variable to `GITHUB_ENV`. +## Passenger Web Docker Configuration + +The passenger web apps (portal and backoffice) are deployed as **Next.js applications** using a dedicated Dockerfile: + +- Dockerfile: `infrastructure/docker/Dockerfile.passenger-web` +- Apps: `apps/edr-passenger-web/portal` and `apps/edr-passenger-web/backoffice` + +### Key differences from freight-web + +| Aspect | Freight Web | Passenger Web | +| --- | --- | --- | +| Framework | Vite (SPA) | Next.js (SSR/SSG) | +| Deployment | Static export + nginx | Node.js server | +| Dockerfile | `Dockerfile.web` | `Dockerfile.passenger-web` | +| Final port (container) | 80 (nginx) | 5174/5184 (Next.js) | +| Build arg | `TURBO_FILTER` | `APP_PACKAGE` + `APP_PATH` + `PORT` | + +### Build arguments + +The Dockerfile accepts the following build args: + +- `APP_PACKAGE`: Turbo package filter (e.g., `@edr/passenger-portal`) +- `APP_PATH`: App directory path (e.g., `apps/edr-passenger-web/portal`) +- `PORT`: Container port to expose (e.g., `5174`) +- `NEXT_PUBLIC_API_URL`: API URL visible to browser (e.g., `https://api.example.com`) + +### Runtime + +The final image runs: + +```bash +node .next/standalone/server.js +``` + +This is the Node.js server provided by Next.js, configured to listen on the `PORT` env var. + ## GitHub Actions Deployment Flow Workflow file: `.github/workflows/deploy.yml` diff --git a/apps/edr-passenger-web/backoffice/next.config.js b/apps/edr-passenger-web/backoffice/next.config.js index a286d1a26..5690be409 100644 --- a/apps/edr-passenger-web/backoffice/next.config.js +++ b/apps/edr-passenger-web/backoffice/next.config.js @@ -1,13 +1,12 @@ /** @type {import('next').NextConfig} */ const nextConfig = { - output: 'export', reactStrictMode: true, transpilePackages: ['@edr/types', '@edr/ui-common'], env: { NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000', }, images: { - unoptimized: true, // Required for static export + unoptimized: true, }, }; diff --git a/apps/edr-passenger-web/portal/next.config.js b/apps/edr-passenger-web/portal/next.config.js index c0d91a2a0..2818d502d 100644 --- a/apps/edr-passenger-web/portal/next.config.js +++ b/apps/edr-passenger-web/portal/next.config.js @@ -1,7 +1,6 @@ /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, - output: 'export', transpilePackages: ['@edr/types', '@edr/ui-common'], images: { unoptimized: true, diff --git a/checkpoint.md b/checkpoint.md index 31eb86b2b..2d5ba3944 100644 --- a/checkpoint.md +++ b/checkpoint.md @@ -35,6 +35,27 @@ 12. Added deployment runbook: - `DEPLOYMENT.md` +## Passenger Web Migration to Next.js (Latest) + +13. Passenger web apps migrated from Vite/SPA to Next.js: + - Updated `apps/edr-passenger-web/portal/next.config.js` and `apps/edr-passenger-web/backoffice/next.config.js`: + - Removed `output: 'export'` to enable server mode + - Preserved `transpilePackages` for @edr/* shared packages +14. Created dedicated Next.js Dockerfile: + - `infrastructure/docker/Dockerfile.passenger-web` + - Uses Node.js server (not nginx) for better Next.js support + - Builds with turbo, deploys with `.next/standalone` server + - Accepts build args: `APP_PACKAGE`, `APP_PATH`, `PORT`, `NEXT_PUBLIC_API_URL` +15. Updated docker-compose.yaml: + - `passenger-portal` and `passenger-backoffice` now use `infrastructure/docker/Dockerfile.passenger-web` + - Port mappings changed from container:80 to container:5174/5184 (Next.js actual ports) + - Updated build args to match new Dockerfile + - Changed env var from `PASSENGER_VITE_API_URL` to `PASSENGER_NEXT_PUBLIC_API_URL` +16. Updated DEPLOYMENT.md: + - Added "Passenger Web Docker Configuration" section + - Documented differences between freight-web (Vite+nginx) and passenger-web (Next.js+Node.js) + - Updated build env file example to use `PASSENGER_NEXT_PUBLIC_API_URL` + ## Key Files to Review - `.github/workflows/deploy.yml` @@ -43,7 +64,10 @@ - `scripts/deploy/create-npmrc.sh` - `apps/edr-passenger-api/docker-entrypoint.sh` - `apps/edr-passenger-api/prisma/seed.ts` -- `DEPLOYMENT.md` +- `infrastructure/docker/Dockerfile.passenger-web` (NEW) +- `apps/edr-passenger-web/portal/next.config.js` (MODIFIED) +- `apps/edr-passenger-web/backoffice/next.config.js` (MODIFIED) +- `DEPLOYMENT.md` (MODIFIED) ## Next Actions @@ -60,4 +84,9 @@ 2. Prisma warns about `package.json#prisma` deprecation (Prisma 7 migration pending). 3. Matrix parallelism increases runner load; ensure self-hosted runner capacity is sufficient. 4. Port collisions are prevented by env-driven mapping, but bad env values can still cause runtime conflicts. +5. Passenger web now uses Next.js server mode (not static export): + - Requires Node.js at runtime (previously could use pure static hosting) + - Deployment must ensure `PASSENGER_NEXT_PUBLIC_API_URL` is set in build env for production deployments + - Each portal/backoffice instance runs its own Node.js process (watch container memory usage) +6. Freight web still uses Vite+nginx (different from passenger web) — maintain both Dockerfiles separately diff --git a/docker-compose.yaml b/docker-compose.yaml index cef40c81e..56f51d62b 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -56,28 +56,30 @@ services: passenger-portal: build: context: . - dockerfile: infrastructure/docker/Dockerfile.web + dockerfile: infrastructure/docker/Dockerfile.passenger-web args: - TURBO_FILTER: "@edr/passenger-portal" + APP_PACKAGE: "@edr/passenger-portal" APP_PATH: apps/edr-passenger-web/portal - NEXT_PUBLIC_API_URL: ${PASSENGER_API_URL:-http://localhost:4000} + PORT: 5174 + NEXT_PUBLIC_API_URL: ${PASSENGER_NEXT_PUBLIC_API_URL:-http://localhost:4000} secrets: - npmrc ports: - - "${PASSENGER_PORTAL_PORT:-5174}:80" + - "${PASSENGER_PORTAL_PORT:-5174}:5174" passenger-backoffice: build: context: . - dockerfile: infrastructure/docker/Dockerfile.web + dockerfile: infrastructure/docker/Dockerfile.passenger-web args: - TURBO_FILTER: "@edr/passenger-backoffice" + APP_PACKAGE: "@edr/passenger-backoffice" APP_PATH: apps/edr-passenger-web/backoffice - NEXT_PUBLIC_API_URL: ${PASSENGER_API_URL:-http://localhost:4000} + PORT: 5184 + NEXT_PUBLIC_API_URL: ${PASSENGER_NEXT_PUBLIC_API_URL:-http://localhost:4000} secrets: - npmrc ports: - - "${PASSENGER_BACKOFFICE_PORT:-5184}:80" + - "${PASSENGER_BACKOFFICE_PORT:-5184}:5184" secrets: npmrc: diff --git a/infrastructure/docker/Dockerfile.passenger-web b/infrastructure/docker/Dockerfile.passenger-web new file mode 100644 index 000000000..ce78c8d16 --- /dev/null +++ b/infrastructure/docker/Dockerfile.passenger-web @@ -0,0 +1,65 @@ +# syntax=docker/dockerfile:1 +# +# Next.js Dockerfile for passenger web (portal + backoffice). +# Builds with turbo, runs with Node.js (not nginx). +# +# Build example (portal): +# DOCKER_BUILDKIT=1 docker build \ +# --build-arg APP_PACKAGE=@edr/passenger-portal \ +# --build-arg APP_PATH=apps/edr-passenger-web/portal \ +# --build-arg PORT=5174 \ +# -f infrastructure/docker/Dockerfile.passenger-web . +# + +ARG APP_PACKAGE=@edr/passenger-portal +ARG APP_PATH=apps/edr-passenger-web/portal +ARG PORT=5174 +ARG NEXT_PUBLIC_API_URL=http://localhost:4000 + +FROM node:24.15.0-alpine AS base +RUN apk add --no-cache libc6-compat +RUN corepack enable +WORKDIR /app + +FROM base AS pruner +ARG APP_PACKAGE +COPY . . +RUN pnpm dlx turbo prune "${APP_PACKAGE}" --docker + +FROM base AS installer +COPY --from=pruner /app/out/json/ . +COPY --from=pruner /app/out/pnpm-lock.yaml ./pnpm-lock.yaml +RUN --mount=type=secret,id=npmrc,target=./.npmrc,required=false \ + --mount=type=cache,id=pnpm,target=/pnpm/store \ + pnpm install --frozen-lockfile + +FROM base AS builder +ARG APP_PACKAGE +ARG APP_PATH +ARG NEXT_PUBLIC_API_URL +ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} +COPY --from=installer /app/ . +COPY --from=pruner /app/out/full/ . +RUN pnpm turbo build --filter="${APP_PACKAGE}..." + +FROM base AS runner +ARG APP_PATH +ARG PORT=5174 +ENV PORT=${PORT} +ENV NODE_ENV=production + +# Copy built app (Next.js output) +COPY --from=builder /app/${APP_PATH}/.next /app/.next +COPY --from=builder /app/${APP_PATH}/public /app/public +COPY --from=builder /app/${APP_PATH}/package.json /app/package.json + +# Copy node_modules (required for Next.js runtime) +COPY --from=builder /app/node_modules /app/node_modules + +# Use node user for security +USER node + +EXPOSE ${PORT} + +# Start Next.js standalone server +CMD ["node", ".next/standalone/server.js"]