Ctrl K
ComunidadGuías…

Dockerfile

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# syntax=docker/dockerfile:1

# Self-hosted Mogplex image, published multi-arch (amd64, arm64) to
# ghcr.io/mogplex/mogplex for every release. One image runs every role in
# docker-compose.yml:
#
#   node server.js                   the Next.js web app (default command)
#   node scripts/migrate.cjs         applies neon/baseline.sql + migrations
#   node scripts/self-host-cron.mjs  calls the cron routes on schedule
#   node scripts/doctor.cjs          checks the deployment's configuration
#
# Every other backing service is bring-your-own and must be reachable from the
# container at runtime: Trigger.dev, sandbox infrastructure, AI providers,
# email, GitHub App, and so on. See docs/self-hosting.md.
#
# The public app URL is read at runtime from APP_URL, so one image serves any
# domain. Other NEXT_PUBLIC_* variables (Sentry DSN, consent backend, Vercel
# sign-in client ID, legacy Supabase keys) are still inlined into the client
# bundle at BUILD time: pass them as --build-arg and rebuild when they change.

ARG NODE_VERSION=22.23.4

FROM node:${NODE_VERSION}-bookworm-slim AS deps
WORKDIR /app
ENV HUSKY=0 \
    NEXT_TELEMETRY_DISABLED=1
RUN corepack enable
# .pnpmfile.cjs is part of the frozen lockfile's checksum; without it the
# install refuses to run.
COPY package.json pnpm-lock.yaml .pnpmfile.cjs ./
RUN pnpm install --frozen-lockfile

FROM node:${NODE_VERSION}-bookworm-slim AS build
WORKDIR /app
ENV HUSKY=0 \
    NEXT_TELEMETRY_DISABLED=1 \
    NEXT_OUTPUT=standalone
RUN corepack enable
COPY --from=deps /app/node_modules ./node_modules
COPY . .

# Client-side settings are inlined at build time. Neon needs no Supabase
# credentials; legacy deployments must explicitly select their backend.
ARG NEXT_PUBLIC_APP_URL
ARG NEXT_PUBLIC_MOGPLEX_DATA_BACKEND=neon
ARG NEXT_PUBLIC_SUPABASE_URL
ARG NEXT_PUBLIC_SUPABASE_ANON_KEY
# Optional client-side integrations.
ARG NEXT_PUBLIC_C15T_URL
ARG NEXT_PUBLIC_SENTRY_DSN
ARG NEXT_PUBLIC_VERCEL_APP_CLIENT_ID
ENV NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL} \
    MOGPLEX_DATA_BACKEND=${NEXT_PUBLIC_MOGPLEX_DATA_BACKEND} \
    NEXT_PUBLIC_MOGPLEX_DATA_BACKEND=${NEXT_PUBLIC_MOGPLEX_DATA_BACKEND} \
    NEXT_PUBLIC_SUPABASE_URL=${NEXT_PUBLIC_SUPABASE_URL} \
    NEXT_PUBLIC_SUPABASE_ANON_KEY=${NEXT_PUBLIC_SUPABASE_ANON_KEY} \
    NEXT_PUBLIC_C15T_URL=${NEXT_PUBLIC_C15T_URL} \
    NEXT_PUBLIC_SENTRY_DSN=${NEXT_PUBLIC_SENTRY_DSN} \
    NEXT_PUBLIC_VERCEL_APP_CLIENT_ID=${NEXT_PUBLIC_VERCEL_APP_CLIENT_ID}

# Next's type-check pass needs more than Node's default heap (it runs out of
# memory near 2 GB). Docker Desktop's default 8 GB VM leaves room for 6 GB.
ENV NODE_OPTIONS=--max-old-space-size=6144

# Runtime secrets come from the environment, never build-time placeholders.
RUN pnpm build
# Bundle the migration runner and setup doctor (with pg) into single files, so
# the runtime image runs them without dev dependencies.
RUN pnpm build:self-host-scripts

FROM node:${NODE_VERSION}-bookworm-slim AS runtime
WORKDIR /app
# Both backend flags come from the build arg the client bundle was built with,
# so the server, the bundle, and the setup doctor agree on the backend.
ARG NEXT_PUBLIC_MOGPLEX_DATA_BACKEND=neon
ENV NODE_ENV=production \
    MOGPLEX_DATA_BACKEND=${NEXT_PUBLIC_MOGPLEX_DATA_BACKEND} \
    NEXT_PUBLIC_MOGPLEX_DATA_BACKEND=${NEXT_PUBLIC_MOGPLEX_DATA_BACKEND} \
    NEXT_TELEMETRY_DISABLED=1 \
    PORT=3000 \
    HOSTNAME=0.0.0.0

RUN groupadd --system nextjs && useradd --system --gid nextjs nextjs

COPY --from=build --chown=nextjs:nextjs /app/.next/standalone ./
COPY --from=build --chown=nextjs:nextjs /app/.next/static ./.next/static
COPY --from=build --chown=nextjs:nextjs /app/public ./public
# The compose `cron` service runs this dependency-free scheduler from the same
# image; it reads the cron routes from vercel.json.
COPY --from=build --chown=nextjs:nextjs /app/vercel.json ./vercel.json
COPY --from=build --chown=nextjs:nextjs /app/scripts/self-host-cron.mjs ./scripts/self-host-cron.mjs
# The compose `migrate` service and the setup doctor; both read ./neon.
COPY --from=build --chown=nextjs:nextjs /app/.next/self-host/apply-neon-migrations.cjs ./scripts/migrate.cjs
COPY --from=build --chown=nextjs:nextjs /app/.next/self-host/doctor.cjs ./scripts/doctor.cjs
COPY --from=build --chown=nextjs:nextjs /app/neon/baseline.sql ./neon/baseline.sql
COPY --from=build --chown=nextjs:nextjs /app/neon/migrations ./neon/migrations

USER nextjs
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
  CMD ["node", "-e", "fetch('http://127.0.0.1:'+(process.env.PORT||3000)+'/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
CMD ["node", "server.js"]