Skip to content

fix(registry): use pnpm deploy for monorepo-aware Dockerfile#110

Merged
mgoldsborough merged 1 commit into
mainfrom
fix/registry-dockerfile-workspace-schemas
May 9, 2026
Merged

fix(registry): use pnpm deploy for monorepo-aware Dockerfile#110
mgoldsborough merged 1 commit into
mainfrom
fix/registry-dockerfile-workspace-schemas

Conversation

@mgoldsborough
Copy link
Copy Markdown
Contributor

@mgoldsborough mgoldsborough commented May 9, 2026

Deploy-blockingmake deploy-all ENV=staging against current main fails the docker build on the registry tsc step:

src/routes/auth.ts(3,53): error TS2307: Cannot find module '@nimblebrain/mpak-schemas' or its corresponding type declarations.
... (15 more such errors across routes/, services/, types.ts)

Root cause

#100 switched the registry's @nimblebrain/mpak-schemas dep from ^0.2.0 (published) to workspace:*. That's the right call — it matches the convention every other package in the workspace already uses (cli, sdk-typescript, web), and removes the publish-bump dance every schemas change otherwise required. The ^0.2.0 pin was actually the band-aid: it dodged the Dockerfile problem by pretending the registry wasn't in a monorepo.

The Dockerfile, however, was written single-package and only copied apps/registry/, never any workspace dep source.

The fix: pnpm deploy

pnpm deploy --filter=<pkg> --prod <out> is pnpm's purpose-built solution for "containerize a workspace package": it walks the full dependency closure (workspace + npm), builds a flattened deployable directory, and resolves all workspace:* links by inlining each workspace package's compiled dist/. One COPY in the runtime stage; future workspace deps require no Dockerfile change.

Considered the simpler patch first (COPY packages/schemas/... then pnpm --filter ... build per-package) but rejected it as per-dep band-aid — the next workspace dep added to the registry would need another COPY pair in both stages.

Builder stage

  • COPY . . brings the whole monorepo in (kept lean by .dockerignore)
  • pnpm install --frozen-lockfile resolves all workspace links
  • pnpm --filter @nimblebrain/mpak-registry exec prisma generate writes the generated client
  • pnpm --filter @nimblebrain/mpak-registry... build builds registry + every transitive workspace dep (... filter syntax)
  • pnpm deploy --filter=@nimblebrain/mpak-registry --prod /deploy flattens everything into /deploy

Production stage

  • One COPY --from=builder /deploy ./ brings everything the runtime needs
  • Two preserved COPY lines for Prisma's generated .prisma/ folder (lives in the pnpm hoisted store, not carried by pnpm deploy — the one true special case)

.dockerignore (new)

Keeps the build context small — excludes every package's node_modules, dist, .astro, .turbo, .git, .env*, test outputs, editor state.

Test plan

  • docker build -f apps/registry/Dockerfile -t mpak-registry:test . — succeeds end-to-end (was failing on tsc)
  • docker run mpak-registry:test — boots fully: Prisma initializes, every module loads, Fastify listens on :3200
  • Inside-image runtime check: node -e "import('@nimblebrain/mpak-schemas').then(m => console.log(typeof m.ServerDetailSchema))"object
  • Post-merge: make deploy-all ENV=staging from deployments/mpak succeeds end-to-end

Fast-merge candidate.

#100 switched the registry's `@nimblebrain/mpak-schemas` dep from
`^0.2.0` (published) to `workspace:*` so schemas changes are
immediately consumable without a publish-bump dance — matching the
convention every other package in the workspace already uses
(`cli`, `sdk-typescript`, `web`). The Dockerfile, however, was
written single-package and only copied `apps/registry/`, never any
workspace dep source. Build then errored across every file
importing schemas:

  src/routes/auth.ts(3,53): error TS2307: Cannot find module
  '@nimblebrain/mpak-schemas' or its corresponding type declarations.
  ... (15 more)

## The fix: `pnpm deploy`

`pnpm deploy --filter=<pkg> --prod <out>` is pnpm's purpose-built
solution for "containerize a workspace package": it walks the full
dependency closure (workspace + npm), builds a flattened deployable
directory, and resolves all `workspace:*` links by bundling each
workspace package's compiled `dist/` inline. Single COPY in the
runtime stage; future workspace deps require no Dockerfile change.

Builder stage:
- `COPY . .` brings the whole monorepo in (kept lean by .dockerignore).
- `pnpm install --frozen-lockfile` resolves all workspace links.
- `pnpm --filter ... exec prisma generate` writes the generated client
  into the pnpm hoisted store.
- `pnpm --filter @nimblebrain/mpak-registry... build` builds the
  registry AND every transitive workspace dep (`...` filter syntax).
- `pnpm deploy --filter=@nimblebrain/mpak-registry --prod /deploy`
  flattens registry + prod deps + workspace closures into /deploy.

Production stage:
- One `COPY --from=builder /deploy ./` brings everything the runtime
  needs — registry dist, schemas dist, every npm prod dep.
- The Prisma generated client is the one exception: its sibling
  `.prisma/` folder lives in the pnpm hoisted store and isn't carried
  by `pnpm deploy`. Two explicit COPY lines preserved from the prior
  Dockerfile handle that special case.

`.dockerignore` (new) keeps the build context small — excludes every
package's `node_modules`, `dist`, `.astro`, `.turbo`, `.git`, `.env*`,
test outputs, editor state.

## Verified locally

- `docker build -f apps/registry/Dockerfile -t mpak-registry:test .` →
  succeeds end-to-end (was failing on the original tsc step).
- `docker run mpak-registry:test` → boots: Prisma initializes, every
  module loads, Fastify listens on :3200.
- `node -e "import('@nimblebrain/mpak-schemas').then(...)"` inside
  the image → schemas resolves, `ServerDetailSchema` is an object.

## Why not the simpler `COPY packages/schemas/...` patch

Considered first, rejected because it's per-dep — every future
workspace dep added to the registry would need another COPY pair in
both stages. `pnpm deploy` is what pnpm's monorepo-Docker docs
recommend and scales to N workspace deps with no Dockerfile churn.
@mgoldsborough mgoldsborough force-pushed the fix/registry-dockerfile-workspace-schemas branch from 3eaa208 to 4d615d6 Compare May 9, 2026 18:31
@mgoldsborough mgoldsborough changed the title fix(registry): copy + build schemas workspace package in Dockerfile fix(registry): use pnpm deploy for monorepo-aware Dockerfile May 9, 2026
@mgoldsborough mgoldsborough merged commit c477c59 into main May 9, 2026
2 checks passed
@mgoldsborough mgoldsborough deleted the fix/registry-dockerfile-workspace-schemas branch May 9, 2026 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant