Files
familysync/apps/api/Dockerfile
T
Lucas Berger b46b25b26b chore(03): Gate 2 stack bring-up — serve PWA from API image, prod env, credential seed
- Dockerfile: build apps/pwa into the production image's ./public so the API
  serves the PWA on a single port (:3000) for the Pangolin/newt tunnel
- docker-compose.yml: set NODE_ENV=production (mount OIDC unconditionally) and
  constrain OIDC_SCOPES=openid profile email offline_access (Authelia rejected
  the empty-default's full scopes_supported with invalid_scope)
- apps/api/scripts/seed-credential.mjs: operator tool to seed member_credentials
  (encrypted Fastmail app password) out-of-band — fills the documented gap
2026-06-06 21:30:58 -04:00

47 lines
2.0 KiB
Docker

# Built from the REPO ROOT context (see docker-compose.yml: build.context: .)
# so the pnpm workspace manifest + lockfile are available for a deterministic,
# workspace-aware install. apps/api is one package in the pnpm workspace.
FROM node:22-alpine AS base
WORKDIR /app
RUN corepack enable pnpm
# Install layer: copy only manifests + lockfile first for cache efficiency.
# Both workspace package.json files are needed so --frozen-lockfile can validate
# every importer in pnpm-lock.yaml. pnpm-workspace.yaml carries allowBuilds.esbuild.
FROM base AS builder
COPY pnpm-workspace.yaml pnpm-lock.yaml package.json ./
COPY apps/api/package.json ./apps/api/
COPY apps/pwa/package.json ./apps/pwa/
RUN pnpm install --frozen-lockfile --filter @familysync/api...
COPY apps/api ./apps/api
RUN pnpm --filter @familysync/api build
FROM base AS dev
WORKDIR /app/apps/api
COPY --from=builder /app /app
CMD ["node", "--watch", "dist/index.js"]
# PWA build stage — produces apps/pwa/dist (relative API paths, env-agnostic).
# Runs in parallel with `builder` under BuildKit; output is copied into the
# production image's ./public so the API serves the PWA on the same port (:3000).
FROM base AS pwa-builder
COPY pnpm-workspace.yaml pnpm-lock.yaml package.json ./
COPY apps/api/package.json ./apps/api/
COPY apps/pwa/package.json ./apps/pwa/
RUN pnpm install --frozen-lockfile --filter @familysync/pwa...
COPY apps/pwa ./apps/pwa
RUN pnpm --filter @familysync/pwa build
FROM base AS production
COPY pnpm-workspace.yaml pnpm-lock.yaml package.json ./
COPY apps/api/package.json ./apps/api/
COPY apps/pwa/package.json ./apps/pwa/
RUN pnpm install --frozen-lockfile --prod --filter @familysync/api...
COPY --from=builder /app/apps/api/dist ./apps/api/dist
WORKDIR /app/apps/api
# PWA static assets built from apps/pwa and served by this API from ./public
# (single-port deployment for the Pangolin/newt tunnel). serveStatic resolves
# ./public relative to the runtime CWD, which is this WORKDIR (/app/apps/api).
COPY --from=pwa-builder /app/apps/pwa/dist ./public
CMD ["node", "dist/index.js"]