Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Keep the docker build context small. The Dockerfile uses `COPY . .` to
# pull the whole monorepo in (so `pnpm deploy` can walk the workspace
# graph); this file makes sure that doesn't include build artifacts,
# installed deps, or local-only state.

# Installed deps — pnpm reinstalls inside the image.
**/node_modules
.pnpm-store

# Build outputs — recreated by `pnpm install` + per-package build.
**/dist
**/build
**/*.tsbuildinfo
**/.astro
**/.turbo
**/.next

# VCS + workspace state.
.git
.github
.claude

# Local environment + secrets — must never enter the image.
.env
.env.*
**/.env
**/.env.*

# Test + coverage outputs.
**/coverage
**/.nyc_output
**/.pytest_cache
**/.ruff_cache

# Editor / OS noise.
.vscode
.idea
.DS_Store
**/*.swp
**/*.swo

# Misc large or sensitive paths that don't need to ship to the registry
# image specifically.
apps/registry/data
apps/web/dist
apps/web/.astro
apps/docs/dist
apps/docs/.astro

# Existing implementation-tracking dirs.
.tasks
69 changes: 34 additions & 35 deletions apps/registry/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,54 +1,53 @@
# Build stage
# Build stage — full monorepo install + build the registry + flatten its
# closure into /deploy via `pnpm deploy`. Workspace deps (e.g. the
# `workspace:*` link to @nimblebrain/mpak-schemas) and any future
# additions are handled automatically — pnpm walks the dependency
# graph and copies what's needed.
FROM node:22-alpine AS builder

RUN corepack enable pnpm

WORKDIR /app

# Copy workspace config
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml tsconfig.base.json ./
# Whole monorepo lands here. `.dockerignore` keeps the context small
# (no node_modules, dist, .git, etc.).
COPY . .

# Copy the registry app
COPY apps/registry/package.json apps/registry/tsconfig.json apps/registry/prisma.config.ts ./apps/registry/
COPY apps/registry/prisma/ ./apps/registry/prisma/
COPY apps/registry/src/ ./apps/registry/src/

# Install dependencies
# One install resolves every workspace package's deps + workspace links.
RUN pnpm install --frozen-lockfile

# Generate Prisma client
RUN cd apps/registry && npx prisma generate
# Generate the Prisma client into the pnpm hoisted store. tsc downstream
# consumes its types; the runtime stage copies the generated artifacts
# explicitly (see below).
RUN pnpm --filter @nimblebrain/mpak-registry exec prisma generate

# Build
RUN cd apps/registry && pnpm build
# Build registry + every transitive workspace dep (schemas, etc.).
RUN pnpm --filter @nimblebrain/mpak-registry... build

# Production stage
FROM node:22-alpine AS production
# Flatten registry + production deps into /deploy. pnpm walks the
# dependency closure and copies every workspace package's `dist/` plus
# every external prod dep — single-stage output, no per-dep COPY pairs
# in the runtime stage as the workspace grows.
RUN pnpm deploy --filter=@nimblebrain/mpak-registry --prod /deploy

RUN corepack enable pnpm
# Production stage — minimal runtime image.
FROM node:22-alpine AS production

WORKDIR /app

# Copy workspace config
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./

# Copy the registry app package.json
COPY apps/registry/package.json ./apps/registry/

# Install production dependencies only
RUN pnpm install --frozen-lockfile --prod

# Copy Prisma schema and generated client (Prisma 7 generates to hoisted node_modules)
COPY --from=builder /app/apps/registry/prisma/ ./apps/registry/prisma/
COPY --from=builder /app/node_modules/.pnpm/@prisma+client*/node_modules/@prisma/client/ ./node_modules/@prisma/client/
# Everything the registry needs at runtime, prepared by `pnpm deploy`:
# its own dist/, its production deps (including @prisma/client base),
# and every workspace dep's compiled output.
COPY --from=builder /deploy ./

# Prisma's generated client lands in the pnpm hoisted store at
# `node_modules/.pnpm/@prisma+client*/node_modules/{.prisma,@prisma/client}/`
# during `prisma generate`. `pnpm deploy` carries the @prisma/client
# package itself but not the sibling .prisma folder where the
# *generated* client and engine binaries live. Copy both explicitly so
# the runtime can find them at the canonical lookup paths.
COPY --from=builder /app/node_modules/.pnpm/@prisma+client*/node_modules/.prisma/ ./node_modules/.prisma/
COPY --from=builder /app/node_modules/.pnpm/@prisma+client-runtime-utils*/node_modules/@prisma/client-runtime-utils/ ./node_modules/@prisma/client-runtime-utils/
COPY --from=builder /app/node_modules/.pnpm/@prisma+client-runtime-utils*/node_modules/@prisma/client-runtime-utils/ ./node_modules/@prisma/client-runtime-utils/

# Copy built output
COPY --from=builder /app/apps/registry/dist/ ./apps/registry/dist/

WORKDIR /app/apps/registry
COPY --from=builder /app/node_modules/.pnpm/@prisma+client*/node_modules/@prisma/client/ ./node_modules/@prisma/client/

# Environment
ENV NODE_ENV=production
Expand Down
Loading