# syntax=docker/dockerfile:1.7 # DataCenterIndex — Next 16 web image (apps/web). No `output: "standalone"` in next.config.ts → `next start` # with a pruned production node_modules. # Build context = repo root: # docker build -f deploy/docker/Dockerfile.web --build-arg NEXT_PUBLIC_API_URL=https://www.datacenterindex.io . ARG NODE_IMAGE=node:22-bookworm-slim ARG PNPM_VERSION=11.1.2 FROM ${NODE_IMAGE} AS base ARG PNPM_VERSION ENV PNPM_HOME=/pnpm \ PATH=/pnpm:$PATH \ npm_config_store_dir=/pnpm/store \ NEXT_TELEMETRY_DISABLED=1 RUN (corepack enable && corepack prepare "pnpm@${PNPM_VERSION}" --activate) \ || npm install -g "pnpm@${PNPM_VERSION}" --no-fund --no-audit # Dev deps are needed for `next build` (tailwind, typescript) → full fetch. FROM base AS fetch WORKDIR /app COPY pnpm-lock.yaml pnpm-workspace.yaml ./ RUN --mount=type=cache,id=dci-pnpm-store,target=/pnpm/store pnpm fetch && rm -rf node_modules # ---------------------------------------------------------------- build FROM fetch AS build ARG NEXT_PUBLIC_API_URL=https://www.datacenterindex.io ARG NEXT_PUBLIC_SITE_URL=https://www.datacenterindex.io ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} \ NEXT_PUBLIC_SITE_URL=${NEXT_PUBLIC_SITE_URL} \ NODE_ENV=production COPY . . RUN --mount=type=cache,id=dci-pnpm-store,target=/pnpm/store \ pnpm install --offline --frozen-lockfile --config.dangerously-allow-all-builds=true --config.confirm-modules-purge=false --filter "@dci/web..." RUN --mount=type=cache,id=dci-next-cache,target=/app/apps/web/.next/cache \ pnpm --filter @dci/web run build # ---------------------------------------------------------------- prod-deps: runtime node_modules only FROM fetch AS prod-deps COPY . . RUN --mount=type=cache,id=dci-pnpm-store,target=/pnpm/store \ pnpm install --offline --frozen-lockfile --config.dangerously-allow-all-builds=true --config.confirm-modules-purge=false --prod --filter "@dci/web..." # ---------------------------------------------------------------- runtime FROM ${NODE_IMAGE} AS runtime ENV NODE_ENV=production \ NEXT_TELEMETRY_DISABLED=1 \ PORT=8310 \ HOSTNAME=0.0.0.0 RUN apt-get update \ && apt-get install -y --no-install-recommends tini ca-certificates \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY --from=prod-deps --chown=node:node /app/package.json /app/pnpm-workspace.yaml /app/tsconfig.base.json ./ COPY --from=prod-deps --chown=node:node /app/node_modules ./node_modules COPY --from=prod-deps --chown=node:node /app/packages/core ./packages/core COPY --from=prod-deps --chown=node:node /app/apps/web/node_modules ./apps/web/node_modules COPY --from=prod-deps --chown=node:node /app/apps/web/package.json /app/apps/web/next.config.ts /app/apps/web/tsconfig.json ./apps/web/ COPY --from=build --chown=node:node /app/apps/web/public ./apps/web/public COPY --from=build --chown=node:node /app/apps/web/.next ./apps/web/.next USER node WORKDIR /app/apps/web EXPOSE 8310 HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \ CMD ["node", "-e", "fetch('http://127.0.0.1:'+(process.env.PORT||8310)+'/').then(r=>process.exit(r.status<500?0:1),()=>process.exit(1))"] ENTRYPOINT ["/usr/bin/tini", "--"] # package.json `start` binds 127.0.0.1 (laptop); inside the container Caddy must reach it → 0.0.0.0. CMD ["node", "node_modules/next/dist/bin/next", "start", "-p", "8310", "-H", "0.0.0.0"]