Dockerfile
Rama main · réplica de lectura del repositorio original.
FROM node:22-bookworm-slim@sha256:83f487e0a63425e5b4d146fb5e5be574bcbe1b7b843d3ebafdd95eaf7767a7e5 AS builder
RUN corepack enable && corepack prepare pnpm@10.12.1 --activate
WORKDIR /app
COPY . .
# Fixed store dir so the runtime stage can reuse the cache offline.
RUN pnpm install --frozen-lockfile --store-dir /pnpm-store
# beta-review: NO default. NEXT_PUBLIC_* is inlined into the bundles at
# build time, and the release workflow publishes ONE image for every
# instance — a localhost default broke voice + realtime after
# `lfctl update apply`. Left empty, the app resolves the endpoints at
# request time (token response / same-origin /livekit + /ws proxy, see
# apps/web/lib/public-endpoints.ts). Local builds may still pass them.
ARG NEXT_PUBLIC_LIVEKIT_URL=
ARG NEXT_PUBLIC_WS_URL=
ENV NEXT_PUBLIC_LIVEKIT_URL=$NEXT_PUBLIC_LIVEKIT_URL
ENV NEXT_PUBLIC_WS_URL=$NEXT_PUBLIC_WS_URL
ENV NODE_ENV=production
# Build only the server-side packages (web, ws-gateway, db, core, etc).
# Skip desktop (Tauri needs Rust) and plugins that are consumed as source.
RUN pnpm --filter @lobbyforge/config build && \
pnpm --filter @lobbyforge/core build && \
pnpm --filter @lobbyforge/plugin-sdk build && \
pnpm --filter @lobbyforge/bot-sdk build && \
pnpm --filter @lobbyforge/db build && \
pnpm --filter @lobbyforge/ui build && \
pnpm --filter @lobbyforge/registry build && \
pnpm --filter @lobbyforge/ws-gateway build && \
pnpm --filter @lobbyforge/plugin-worker build && pnpm --filter @lobbyforge/web build
FROM node:22-bookworm-slim@sha256:83f487e0a63425e5b4d146fb5e5be574bcbe1b7b843d3ebafdd95eaf7767a7e5 AS runtime
# PostgreSQL client tools for lfctl backup create/restore (pg_dump, pg_restore, psql).
# libpcre2-8-0 is listed so apt upgrades it to the patched Debian build: the
# base image lags behind Debian's pcre2 security fixes (CVE-2026-103111 and
# earlier, fixed in 10.42-1+deb12u2).
RUN apt-get update && apt-get install -y --no-install-recommends postgresql-client libpcre2-8-0 && rm -rf /var/lib/apt/lists/*
RUN corepack enable && corepack prepare pnpm@10.12.1 --activate
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /pnpm-store /pnpm-store
COPY --from=builder /app /app
# Strip devDependencies from the RUNTIME image (Trivy CRITICAL gate:
# vitest/happy-dom/tar CVEs were shipping because the builder's full
# node_modules was copied). `pnpm prune` proved pathologically slow in
# CI (>1h); instead rebuild node_modules PROD-ONLY, offline, from the
# store the builder already populated — same lockfile, no network.
# Workspace symlinks (@lobbyforge/db etc.) are recreated against the
# packages' built dist/, which the COPY above preserved.
# Remove EVERY node_modules (root AND per-package — the builder copy
# leaves nested ones with dev-only transitive deps like tar@7.4.3).
# Wipe EVERY node_modules (root AND per-package — the builder copy
# leaves nested ones with dev-only transitive deps), rebuild PROD-ONLY
# offline from the builder's store, then drop the store (it also holds
# DEV tarballs) AND the package managers themselves — pnpm's corepack
# download bundles a vulnerable tar (CVE-2026-59873) and npm's manifests
# ship more. The runtime needs NODE only; the web service invokes
# next's bin directly.
RUN find /app -name node_modules -type d -prune -exec rm -rf {} + && pnpm install --prod --frozen-lockfile --offline --ignore-scripts --store-dir /pnpm-store && rm -rf /pnpm-store /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx /root/.cache/node/corepack
# Run as non-root — the node image ships with a `node` user (uid 1000).
RUN chown -R node:node /app
USER node
EXPOSE 3000 3001
# libuv's threadpool (default 4 threads) runs scrypt password hashing,
# zlib, file I/O and dns.lookup (getaddrinfo) for the whole process; a few
# slow lookups (the plugin installer, the directory, CAPTCHA siteverify)
# must not stall sign-ins. Bot event deliveries resolve off the pool
# (c-ares, 2 s deadline), but the web server still gets a bigger pool.
# Read once at process start; override in .env.prod (env_file) if needed.
ENV UV_THREADPOOL_SIZE=16
# Start only the Next.js web server (direct node invocation — no pnpm
# in the runtime image). The ws-gateway runs as a separate Compose
# service with its own CMD override.
WORKDIR /app/apps/web
CMD ["node", "node_modules/next/dist/bin/next", "start"]