Container image registry

This commit is contained in:
adilallo
2026-05-23 13:30:34 -06:00
parent c663e051da
commit 2fd20d5b2a
6 changed files with 230 additions and 19 deletions
+42 -12
View File
@@ -1,6 +1,7 @@
# Optional production image (Next.js standalone output + Prisma).
# Build: docker build -t community-rule .
# Run: pass DATABASE_URL, SESSION_SECRET, etc. at runtime (see .env.example).
# Production image: Next.js standalone output + Prisma, packaged for Cloudron.
# Build / push: ./scripts/docker-release.sh
# Install: cloudron install (reads CloudronManifest.json from repo root)
# See docs/guides/ops-backend-deploy.md §9.
FROM node:20-bookworm-slim AS base
WORKDIR /app
@@ -9,7 +10,19 @@ ENV NEXT_TELEMETRY_DISABLED=1
FROM base AS deps
RUN apt-get update -y && apt-get install -y openssl && rm -rf /var/lib/apt/lists/*
COPY package.json package-lock.json ./
RUN npm ci --no-audit --fund=false
# --legacy-peer-deps: tolerates two pre-existing peer-dependency mismatches
# that local `npm install` papers over but container `npm ci` (npm 10.8.x)
# refuses:
# 1. next-intl@3.26.5 declares peer next "^10..^15" while the project is
# on next@16. Upgrading to next-intl@4 supports next 16 cleanly.
# 2. @storybook/addon-interactions@8 vs storybook@10 (devDep only;
# the addon was merged into Storybook 8 core and can be removed).
# Drop this flag in the follow-up that lands next-intl@4 + Storybook
# cleanup together.
# --ignore-scripts: skips the project `postinstall` (`npm rebuild lightningcss
# && prisma generate`). The Prisma schema is not yet present in this stage;
# the builder stage runs `prisma generate` after `COPY . .`.
RUN npm ci --no-audit --fund=false --legacy-peer-deps --ignore-scripts
FROM base AS builder
RUN apt-get update -y && apt-get install -y openssl && rm -rf /var/lib/apt/lists/*
@@ -19,17 +32,34 @@ RUN npx prisma generate
RUN npm run build
FROM base AS runner
RUN apt-get update -y && apt-get install -y openssl && rm -rf /var/lib/apt/lists/*
# openssl: Prisma engines. gosu: privilege drop in start.sh after chown.
RUN apt-get update -y && apt-get install -y openssl gosu && rm -rf /var/lib/apt/lists/*
ENV NODE_ENV=production
RUN groupadd --system --gid 1001 nodejs && useradd --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
COPY --from=builder /app/prisma ./prisma
# Reuse the `node` user (uid/gid 1000) shipped in node:20-bookworm-slim.
# Cloudron's localstorage addon mounts /app/data with root:root ownership at
# runtime; start.sh chowns it to node:node before dropping privileges.
COPY --from=builder --chown=node:node /app/public ./public
COPY --from=builder --chown=node:node /app/.next/standalone ./
COPY --from=builder --chown=node:node /app/.next/static ./.next/static
COPY --from=builder --chown=node:node /app/prisma ./prisma
# Prisma CLI is in devDependencies and is not included in the Next.js
# standalone output. Copy it explicitly so start.sh can run migrations.
COPY --from=builder --chown=node:node /app/node_modules/prisma ./node_modules/prisma
COPY --from=builder --chown=node:node /app/node_modules/.bin/prisma ./node_modules/.bin/prisma
# Cloudron's runtime rootfs is read-only except /tmp, /run, /app/data.
# Three marketing routes use ISR (`revalidate`) and write to .next/cache;
# redirect that path to /tmp/next-cache via a baked-in symlink so writes land
# on a writable mount at runtime.
RUN mkdir -p .next && ln -sfn /tmp/next-cache .next/cache
COPY --chown=node:node scripts/start.sh /start.sh
RUN chmod +x /start.sh
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]
CMD ["/start.sh"]