apps/landing/Dockerfile
Rama main · réplica de lectura del repositorio original.
# Production Next.js image for the community landing/marketing site.
#
# Build context is the `community/` root (see ../../docker-compose.yml), not this
# directory, so every COPY below is rooted at `apps/landing/...`.
#
# apps/landing/next.config.ts only enables `output: "standalone"` when the
# NEXT_OUTPUT build-time env var is exactly "standalone" (verified against
# next.config.ts, which also sets security headers unconditionally). Setting
# NEXT_OUTPUT below is what makes `next build` emit .next/standalone.
#
# NEXT_PUBLIC_* vars are baked into the client bundle at build time (they run
# in the end user's browser, not inside this container), so they must be the
# host-facing URLs docker-compose publishes each service on (localhost:<port>),
# not the internal Docker service names -- matches the original app's build-time
# env handling and infra/deploy/landing/Dockerfile.
FROM node:20-alpine AS deps
WORKDIR /app
COPY apps/landing/package.json apps/landing/package-lock.json ./
RUN npm ci
FROM node:20-alpine AS builder
WORKDIR /app
ENV NEXT_OUTPUT=standalone
# Verified via next.config.ts + grep of process.env.NEXT_PUBLIC_* under
# apps/landing/{app,components,lib} -- landing only reads these four.
ARG NEXT_PUBLIC_API_URL=http://localhost:4000
ARG NEXT_PUBLIC_LANDING_URL=http://localhost:3001
ARG NEXT_PUBLIC_DASHBOARD_URL=http://localhost:53000
ARG NEXT_PUBLIC_ADMIN_URL=http://localhost:3002
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL \
NEXT_PUBLIC_LANDING_URL=$NEXT_PUBLIC_LANDING_URL \
NEXT_PUBLIC_DASHBOARD_URL=$NEXT_PUBLIC_DASHBOARD_URL \
NEXT_PUBLIC_ADMIN_URL=$NEXT_PUBLIC_ADMIN_URL
COPY --from=deps /app/node_modules ./node_modules
COPY apps/landing/. .
# Verified: apps/landing/package.json "build" == "next build".
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production \
HOSTNAME=0.0.0.0 \
PORT=3001
RUN addgroup --system --gid 1001 nodejs \
&& adduser --system --uid 1001 nextjs
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3001
# Probe a static asset, NOT `/`. The root of this app is a server-rendered
# page; probing it every 15 s made the container render its own homepage
# 5,760 times a day, each render fanning out to the API and from there to
# Postgres (for landing: 3 catalog calls + stats per render). Measured on
# 2026-09-22 as the bulk of a steady ~10 GB/day of Supabase egress. The
# favicon is served straight from the standalone build with no data fetch,
# so it still proves the Node server is up and answering HTTP, which is all
# a liveness probe should prove. 60 s is plenty for a restart-on-failure
# policy; a 15 s cadence was never load-bearing for anything.
HEALTHCHECK --interval=60s --timeout=5s --start-period=15s --retries=3 \
CMD node -e "fetch('http://127.0.0.1:' + (process.env.PORT || 3001) + '/favicon.ico').then(r => process.exit(r.status < 500 ? 0 : 1)).catch(() => process.exit(1))"
# Verified: .next/standalone always emits server.js as the entrypoint.
CMD ["node", "server.js"]