# syntax=docker/dockerfile:1.7 # ---- deps stage: install with cache-friendly pnpm fetch ---- FROM node:22-alpine AS deps WORKDIR /app RUN corepack enable && corepack prepare pnpm@latest-9 --activate COPY package.json pnpm-lock.yaml ./ RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store \ pnpm fetch # ---- build stage: compile TypeScript ---- FROM deps AS build COPY . . RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store \ pnpm install --frozen-lockfile --offline RUN pnpm build RUN pnpm prune --prod # ---- runtime: slim, non-root ---- FROM node:22-alpine AS runtime WORKDIR /app RUN addgroup -S app && adduser -S -G app app COPY --from=build --chown=app:app /app/node_modules ./node_modules COPY --from=build --chown=app:app /app/dist ./dist COPY --from=build --chown=app:app /app/package.json ./package.json USER app # Only the TCP port is exposed. METRICS_PORT (9090) is in the config schema but # no HTTP server runs today — task 1.10 (observability) adds that server. EXPOSE 5027 # HEALTHCHECK deferred — re-add `wget -qO- http://localhost:${METRICS_PORT}/readyz` # when task 1.10 (observability) ships and the HTTP server is running. CMD ["node", "dist/main.js"]