# syntax=docker/dockerfile:1.7 # The build stage contains the package manager and compiler. The final image # only contains the traced Next.js server and its production dependencies. # Install and trace native dependencies on the target platform as well. FROM node:24-bookworm-slim@sha256:55fb5f5a527ea2c5c4a95f963e48ef90aa38c7b346054fdc8ee9957a2b55d205 AS base ENV PNPM_HOME=/pnpm ENV PATH=$PNPM_HOME:$PATH RUN corepack enable && corepack prepare pnpm@10.28.0 --activate FROM base AS dependencies WORKDIR /app COPY package.json pnpm-lock.yaml ./ COPY patches ./patches RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store \ pnpm install --frozen-lockfile FROM dependencies AS build COPY . . # Runtime configuration is intentionally not supplied at build time. The # application validates operator settings during process startup instead. ENV NEXT_TELEMETRY_DISABLED=1 RUN pnpm run build FROM node:24-bookworm-slim@sha256:55fb5f5a527ea2c5c4a95f963e48ef90aa38c7b346054fdc8ee9957a2b55d205 AS runtime ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 ENV HOSTNAME=0.0.0.0 ENV PORT=3000 WORKDIR /app RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/lib/node_modules/corepack \ && rm -f /usr/local/bin/npm /usr/local/bin/npx /usr/local/bin/corepack \ /usr/local/bin/pnpm /usr/local/bin/pnpx /usr/local/bin/yarn /usr/local/bin/yarnpkg \ && apt-get update \ && apt-get install --yes --no-install-recommends apt ca-certificates libapt-pkg6.0 libpcre2-8-0 perl-base \ && rm -rf /var/lib/apt/lists/* \ && groupadd --gid 10001 minddy \ && useradd --uid 10001 --gid minddy --create-home --shell /usr/sbin/nologin minddy COPY --from=build --chown=minddy:minddy /app/public ./public COPY --from=build --chown=minddy:minddy /app/supabase/email-templates ./supabase/email-templates COPY --from=build --chown=minddy:minddy /app/.next/standalone ./ COPY --from=build --chown=minddy:minddy /app/.next/static ./.next/static USER minddy # Liveness alone cannot detect a native module copied from another architecture. # Execute an image operation in every target image before it can be published. RUN node -e "require('sharp')({ create: { width: 1, height: 1, channels: 4, background: '#000000' } }).png().toBuffer().then(() => console.log('Native image operation passed for ' + process.arch), (error) => { console.error(error); process.exit(1); })" EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ CMD node -e "fetch('http://127.0.0.1:3000/api/health').then((response) => process.exit(response.ok ? 0 : 1)).catch(() => process.exit(1))" CMD ["node", "server.js"]