Add 'RUN --mount=type=cache,target=/pnpm-store' to all 3 pnpm install stages (builder/pwa-builder/production) with --store-dir /pnpm-store, plus the '# syntax=docker/dockerfile:1' directive. Set DOCKER_BUILDKIT=1 on the publish build step so the legacy builder can't break on the mount syntax. sharing=locked because builder and pwa-builder run in parallel. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
55 lines
2.6 KiB
Docker
55 lines
2.6 KiB
Docker
# syntax=docker/dockerfile:1
|
|
# 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 --mount=type=cache,target=/pnpm-store,id=pnpm-store,sharing=locked \
|
|
pnpm install --frozen-lockfile --filter @familysync/api... --store-dir /pnpm-store
|
|
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 --mount=type=cache,target=/pnpm-store,id=pnpm-store,sharing=locked \
|
|
pnpm install --frozen-lockfile --filter @familysync/pwa... --store-dir /pnpm-store
|
|
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 --mount=type=cache,target=/pnpm-store,id=pnpm-store,sharing=locked \
|
|
pnpm install --frozen-lockfile --prod --filter @familysync/api... --store-dir /pnpm-store
|
|
COPY --from=builder /app/apps/api/dist ./apps/api/dist
|
|
WORKDIR /app/apps/api
|
|
# Enforce production identity — engages the NODE_ENV=production hard guard
|
|
# in devBypass.ts, preventing dev-bypass activation even if DEV_AUTH_BYPASS
|
|
# is accidentally set in the container environment. (D-07)
|
|
ENV NODE_ENV=production
|
|
# 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"]
|