|
| 1 | +# Build from repo root: docker build -f showcase/shell-dashboard/Dockerfile . |
| 2 | +# The build context MUST be the repository root; this Dockerfile copies from |
| 3 | +# showcase/scripts, showcase/shared, showcase/packages, showcase/shell (for |
| 4 | +# generated data JSON that shell-dashboard imports at build time), and |
| 5 | +# showcase/shell-dashboard. |
| 6 | + |
| 7 | +FROM node:20-slim AS builder |
| 8 | +ARG COMMIT_SHA=unknown |
| 9 | +ARG BRANCH=unknown |
| 10 | +# NEXT_PUBLIC_BASE_URL is inlined by Next.js at `next build`. Pass it via: |
| 11 | +# docker build --build-arg NEXT_PUBLIC_BASE_URL=https://... |
| 12 | +# shell-dashboard's next.config.ts does not currently require it, but we |
| 13 | +# keep the plumbing consistent with shell-docs so callers (Railway, CI) set |
| 14 | +# a single canonical host for the build. |
| 15 | +ARG NEXT_PUBLIC_BASE_URL |
| 16 | +ENV NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL} |
| 17 | +WORKDIR /app |
| 18 | + |
| 19 | +# Fail fast if COMMIT_SHA was not supplied: shipping the default "unknown" |
| 20 | +# silently poisons build metadata (footer, health checks, error reports). |
| 21 | +RUN if [ "$COMMIT_SHA" = "unknown" ] || [ -z "$COMMIT_SHA" ]; then \ |
| 22 | + echo "ERROR: COMMIT_SHA must be set via --build-arg (got '$COMMIT_SHA')" >&2; \ |
| 23 | + exit 1; \ |
| 24 | + fi |
| 25 | + |
| 26 | +# NOTE on SWC native bindings: Next.js recommends installing `libc6-compat` |
| 27 | +# on Alpine-based images so @next/swc-* native binaries load. We use |
| 28 | +# `node:20-slim` (Debian bookworm), which ships with glibc, so no compat |
| 29 | +# shim is required. If we ever switch to `node:20-alpine`, add: |
| 30 | +# RUN apk add --no-cache libc6-compat |
| 31 | + |
| 32 | +# Copy manifests + lockfiles first for cached, reproducible installs. |
| 33 | +# Both showcase/scripts/ and showcase/shell-dashboard/ ship lockfiles, so |
| 34 | +# use `npm ci` in both stages for deterministic, reproducible installs. |
| 35 | +COPY showcase/scripts/package.json showcase/scripts/package-lock.json ./scripts/ |
| 36 | +COPY showcase/shell-dashboard/package.json showcase/shell-dashboard/package-lock.json ./shell-dashboard/ |
| 37 | + |
| 38 | +RUN cd scripts && npm ci --silent \ |
| 39 | + && cd ../shell-dashboard && npm ci --silent |
| 40 | + |
| 41 | +# Copy source |
| 42 | +COPY showcase/shared/ ./shared/ |
| 43 | +COPY showcase/packages/ ./packages/ |
| 44 | +COPY showcase/scripts/ ./scripts/ |
| 45 | +# shell-dashboard imports generated JSON from ../../../shell/src/data/ at |
| 46 | +# build time (registry.json, docs-status.json, status.json). Copy the shell |
| 47 | +# package so those imports resolve; the generators below refresh them. |
| 48 | +COPY showcase/shell/ ./shell/ |
| 49 | +COPY showcase/shell-dashboard/ ./shell-dashboard/ |
| 50 | + |
| 51 | +# Bake commit info into Next.js build |
| 52 | +ENV NEXT_PUBLIC_COMMIT_SHA=${COMMIT_SHA} |
| 53 | +ENV NEXT_PUBLIC_BRANCH=${BRANCH} |
| 54 | + |
| 55 | +# Generate registry + docs status + demo content, then build Next.js. |
| 56 | +# Mirrors shell-dashboard/package.json "build" script exactly. |
| 57 | +RUN cd scripts && node node_modules/tsx/dist/cli.mjs generate-registry.ts \ |
| 58 | + && node node_modules/tsx/dist/cli.mjs probe-docs.ts \ |
| 59 | + && node node_modules/tsx/dist/cli.mjs bundle-demo-content.ts \ |
| 60 | + && cd ../shell-dashboard && node_modules/.bin/next build |
| 61 | + |
| 62 | +FROM node:20-slim AS runner |
| 63 | +# Re-declare build args in this stage so ENV interpolation below resolves. |
| 64 | +# ARGs do not cross stages in multi-stage builds. |
| 65 | +ARG COMMIT_SHA=unknown |
| 66 | +ARG BRANCH=unknown |
| 67 | +WORKDIR /app |
| 68 | +ENV NODE_ENV=production |
| 69 | +ENV PORT=10000 |
| 70 | +ENV NEXT_PUBLIC_COMMIT_SHA=${COMMIT_SHA} |
| 71 | +ENV NEXT_PUBLIC_BRANCH=${BRANCH} |
| 72 | + |
| 73 | +COPY --from=builder /app/shell-dashboard/.next ./.next |
| 74 | +COPY --from=builder /app/shell-dashboard/node_modules ./node_modules |
| 75 | +COPY --from=builder /app/shell-dashboard/package.json ./ |
| 76 | +COPY --from=builder /app/shell-dashboard/package-lock.json ./ |
| 77 | + |
| 78 | +# Strip dev dependencies (tailwindcss/postcss/tsx/typescript/@types/*) from |
| 79 | +# the runtime image — they are only needed during `next build`. |
| 80 | +RUN npm prune --omit=dev |
| 81 | + |
| 82 | +EXPOSE 10000 |
| 83 | +# Invoke next directly (no npx) to avoid runtime network fallback |
| 84 | +CMD ["node_modules/.bin/next", "start", "-p", "10000"] |
0 commit comments