# Images for the GregKilmer.com stack on Cosmos. One file, one target per service: # # docker build --target check . runs `npm run check` (typecheck and tests) # docker build --target content . the content service and MCP server # docker build --target admin . the admin page (tailnet only) # docker build --target site . the public site # # deploy/deploy.sh builds check first, so a red check stops a deploy. # See docs/deploy.md. # Pinned by version (Node 22.20, released 2025-09). Override with --build-arg to # pull through a mirror. ARG NODE_IMAGE=node:22.20.0-alpine # ---------- package manifests, then every workspace's dependencies ---------- FROM ${NODE_IMAGE} AS manifests WORKDIR /app COPY package.json package-lock.json ./ COPY packages/schema/package.json packages/schema/ COPY packages/ui/package.json packages/ui/ COPY services/content/package.json services/content/ COPY services/admin/package.json services/admin/ COPY services/site/package.json services/site/ COPY tools/migrate/package.json tools/migrate/ FROM manifests AS deps RUN npm ci --no-audit --no-fund # ---------- typecheck and tests ---------- FROM deps AS check COPY . . RUN npm run check # ---------- the site's server build ---------- FROM deps AS site-build # Workspace packages' tsconfigs extend the root one; Vite reads them during the build. COPY tsconfig.base.json ./ COPY packages packages COPY services/site services/site RUN npm run build -w @gk/site # ---------- each service's production dependencies only ---------- FROM manifests AS content-deps RUN npm ci --omit=dev --no-audit --no-fund -w @gk/content && npm cache clean --force FROM manifests AS admin-deps RUN npm ci --omit=dev --no-audit --no-fund -w @gk/admin && npm cache clean --force FROM manifests AS site-deps RUN npm ci --omit=dev --no-audit --no-fund -w @gk/site && npm cache clean --force # ---------- shared runtime base ---------- FROM ${NODE_IMAGE} AS runtime WORKDIR /app ENV NODE_ENV=production HOST=0.0.0.0 COPY package.json ./ COPY packages/schema/package.json packages/schema/ COPY packages/schema/src packages/schema/src # ---------- content service ---------- FROM runtime AS content COPY --from=content-deps /app/node_modules node_modules COPY services/content/package.json services/content/ COPY services/content/src services/content/src # The vault's Site folder and the data folder (SQLite and saved form attachments). ENV PORT=4310 SITE_DIR=/vault/Site DATA_DIR=/data EXPOSE 4310 HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ CMD wget -qO- http://127.0.0.1:4310/health >/dev/null || exit 1 USER node CMD ["node", "--disable-warning=ExperimentalWarning", "--import", "tsx", "services/content/src/main.ts"] # ---------- admin page ---------- FROM runtime AS admin COPY --from=admin-deps /app/node_modules node_modules COPY services/admin/package.json services/admin/ COPY services/admin/src services/admin/src COPY services/admin/public services/admin/public ENV PORT=4320 EXPOSE 4320 HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ CMD wget -qO- http://127.0.0.1:4320/health >/dev/null || exit 1 USER node CMD ["node", "--import", "tsx", "services/admin/src/main.ts"] # ---------- public site ---------- FROM runtime AS site COPY --from=site-deps /app/node_modules node_modules COPY --from=site-build /app/services/site/dist services/site/dist ENV PORT=4321 EXPOSE 4321 HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ CMD wget -qO- http://127.0.0.1:4321/ >/dev/null || exit 1 USER node CMD ["node", "services/site/dist/server/entry.mjs"]