72 lines
3.2 KiB
Docker
72 lines
3.2 KiB
Docker
# =============================================================================
|
|
# 0pt web console -- Dockerfile for Coolify (SIAX Cloud)
|
|
# =============================================================================
|
|
# This repo's deployable service is the Next.js 16 app at the repo root
|
|
# (package.json `start` == `next start`, liveness at GET /api/health). Unlike
|
|
# the tsx backend services elsewhere in the fleet (aud0/n0d/api0), a Next app
|
|
# needs a real build step, so this is a multi-stage build: install+build, then
|
|
# a slim runtime that runs the built output as the non-root `node` user.
|
|
#
|
|
# node:24-alpine matches the tag already proven in ../aud0 and ../api0. `wget`
|
|
# is added to the runtime stage so Coolify's container healthcheck has a binary
|
|
# to hit /api/health (bare node:*-alpine ships neither curl nor wget).
|
|
#
|
|
# next.config.mjs does NOT set `output: "standalone"` (that would be a source
|
|
# change, out of Wave-1 scope), so the runtime stage carries node_modules + the
|
|
# .next build output and runs `next start` directly.
|
|
# =============================================================================
|
|
|
|
# ---- build stage ------------------------------------------------------------
|
|
FROM node:24-alpine AS builder
|
|
WORKDIR /app
|
|
|
|
ENV NEXT_TELEMETRY_DISABLED=1
|
|
|
|
# Enable corepack (pnpm@9 pinned below to match pnpm-lock.yaml lockfileVersion 9.0).
|
|
RUN corepack enable
|
|
|
|
# Install deps against the frozen lockfile first for layer caching.
|
|
# --ignore-workspace: the repo's pnpm-workspace.yaml is a v0-export artifact that
|
|
# carries only an `allowBuilds:` block and NO `packages:` field, which makes pnpm
|
|
# abort with "packages field missing or empty". There are no real workspace
|
|
# members (only the root package.json), so ignoring the workspace file is
|
|
# semantically a no-op and lets the frozen install resolve the root deps cleanly.
|
|
COPY package.json pnpm-lock.yaml .npmrc ./
|
|
RUN corepack prepare pnpm@9 --activate && pnpm install --frozen-lockfile --ignore-workspace
|
|
|
|
# Build the app. The lib/* clients (db, stripe, ...) are lazy + env-guarded, so
|
|
# `next build` succeeds without any runtime secrets present.
|
|
# --ignore-workspace again here: `COPY . .` reintroduces the v0 pnpm-workspace.yaml,
|
|
# and `pnpm run` re-parses it (same "packages field missing" abort) unless ignored.
|
|
COPY . .
|
|
RUN pnpm --ignore-workspace run build
|
|
|
|
# ---- runtime stage ----------------------------------------------------------
|
|
FROM node:24-alpine AS runtime
|
|
WORKDIR /app
|
|
|
|
ENV NODE_ENV=production
|
|
ENV NEXT_TELEMETRY_DISABLED=1
|
|
ENV HOSTNAME=0.0.0.0
|
|
ENV PORT=3000
|
|
|
|
RUN apk add --no-cache wget
|
|
|
|
# Built artifacts + resolved dependencies from the build stage. .next is chowned
|
|
# so `next start` can write its runtime cache as the non-root user.
|
|
COPY --from=builder /app/node_modules ./node_modules
|
|
COPY --from=builder --chown=node:node /app/.next ./.next
|
|
COPY --from=builder /app/public ./public
|
|
COPY --from=builder /app/package.json ./package.json
|
|
COPY --from=builder /app/next.config.mjs ./next.config.mjs
|
|
|
|
USER node
|
|
|
|
EXPOSE 3000
|
|
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
|
|
CMD wget -qO- http://127.0.0.1:3000/api/health >/dev/null 2>&1 || exit 1
|
|
|
|
# Invoke the next binary directly (pnpm/corepack are not set up in this stage).
|
|
CMD ["node_modules/.bin/next", "start"]
|