diff --git a/apps/webui/Dockerfile b/apps/webui/Dockerfile index 7b53d70..cf300c1 100644 --- a/apps/webui/Dockerfile +++ b/apps/webui/Dockerfile @@ -17,6 +17,25 @@ COPY eslint.config.js .eslintrc.cjs .prettierrc ./ RUN pnpm install --frozen-lockfile=false RUN pnpm --filter @nexumi/shared build RUN pnpm --filter @nexumi/webui prisma:generate +# `next build` statically evaluates route/module code while collecting page +# data. Our env schema and Prisma client are validated eagerly at import +# time, so the build needs *some* well-formed values even though no real +# secrets or network access are available at build time. These placeholders +# are only used for that static analysis step and are always overridden by +# the real values from `.env` (via docker-compose `env_file`) at container +# start, since this ENV only applies to this intermediate build stage and is +# never copied into the `runner` stage / final image. +# Note: this intentionally triggers a "SecretsUsedInArgOrEnv" lint warning +# because of the variable names — the values below are non-sensitive +# placeholders, not real secrets. +ENV NODE_ENV=production \ + DATABASE_URL=postgresql://build:build@localhost:5432/build \ + REDIS_URL=redis://localhost:6379 \ + BOT_CLIENT_ID=0000000000000000000 \ + BOT_CLIENT_SECRET=build-time-placeholder \ + WEBUI_URL=http://localhost:3000 \ + SESSION_SECRET=build-time-placeholder-session-secret-32chars \ + DEFAULT_LOCALE=de RUN pnpm --filter @nexumi/webui build FROM base AS runner diff --git a/apps/webui/src/lib/redis.ts b/apps/webui/src/lib/redis.ts index 9bdc4fc..6a50354 100644 --- a/apps/webui/src/lib/redis.ts +++ b/apps/webui/src/lib/redis.ts @@ -3,8 +3,19 @@ import { env } from './env'; const globalForRedis = globalThis as unknown as { __nexumiRedis?: Redis }; -export const redis: Redis = globalForRedis.__nexumiRedis ?? new Redis(env.REDIS_URL, { - maxRetriesPerRequest: 3 +export const redis: Redis = + globalForRedis.__nexumiRedis ?? + new Redis(env.REDIS_URL, { + maxRetriesPerRequest: 3, + // Defer the actual TCP connection until the first command is issued. + // This keeps module import side-effect free, which matters for + // Next.js's build-time "collect page data" step (no network access + // there) and avoids unhandled 'error' events on unreachable hosts. + lazyConnect: true + }); + +redis.on('error', (error) => { + console.error('[redis]', error.message); }); if (env.NODE_ENV !== 'production') {