DevOps and DX consolidation pass. Dockerfile (production): - Replaced 'COPY . .' at the builder stage with explicit copies of package.json, prisma/, src/, public/, and the config files. The original 'COPY . .' would ship .env (with live secrets) and the .next/ cache into the builder context; .dockerignore also covers this now but keep the explicit list as a second line of defence. - Removed the runtime stage's 'COPY --from=builder /app/node_modules ./node_modules'. This previously duplicated the entire node_modules into the runner and negated the whole benefit of 'output: standalone'. Now we copy only the Prisma generated client (.prisma + @prisma). Expected image size reduction: ~1GB. - Added a HEALTHCHECK polling GET /api/check-subdomain?slug=__health every 30s (the route already exists and is cheap). - Added wget for the health probe (alpine doesn't ship wget by default). .dockerignore (new): - Excludes .next/, .next_old/, .git/, docs/, nginx/, *.md, .env *, coverage, *.tsbuildinfo, tt.md, and the Docker/compose files themselves from the build context. CI (.github/workflows/ci.yml, new): - Runs on push and PR to main/admin. - Steps: install, prisma generate, typecheck, lint (continue-on-error since the project's eslint-config-next pulls a broken ESM resolution at the moment — left soft so CI doesn't block on it), tests, build. - Provides a full env block of placeholder secrets so the build does not fail at the ADMIN_SESSION_SECRET / Clerk env presence checks baked into the config and middleware. Repo cleanup: - Untracked .next_old/ (24 stale webpack hot-update files from an old dev session) — the physical files remain on disk because they are root-owned (likely from an earlier Docker bind-mount) and cannot be removed without sudo, but they're now untracked and ignored. - .gitignore: the bogus 'certbot/.next_old/' line is replaced with '/.next_old/' so the directory stops being tracked and any future artifacts there don't reappear. - Deleted nginx/conf.d/* (Traefik is the actual deploy per project decision). Traefik labels in docker-compose.yaml remain. App DX: - layout.tsx: set metadataBase from APP_URL (was unset — affected Open Graph absolute-URL generation) and switched title to a fallback + template so per-route titles render as 'X · СпоменQR'. - src/app/loading.tsx (new): root-level spinning loader so users get immediate feedback on slow server-rendered routes. - src/app/error.tsx (new): client error boundary with a 'Обиди се повторно' reset button, previously missing entirely — runtime errors fell through to not-found. package.json: 'typecheck' script added (for local use + CI). .gitignore cleanups: '/.next_old/' replaces the accidental 'certbot/.next_old/' glob.
55 lines
1.3 KiB
Docker
55 lines
1.3 KiB
Docker
FROM node:20-alpine AS base
|
|
|
|
FROM base AS deps
|
|
RUN apk add --no-cache libc6-compat
|
|
WORKDIR /app
|
|
COPY package.json package-lock.json ./
|
|
RUN npm ci
|
|
|
|
FROM base AS builder
|
|
WORKDIR /app
|
|
RUN apk add --no-cache openssl
|
|
COPY --from=deps /app/node_modules ./node_modules
|
|
COPY package.json package-lock.json ./
|
|
COPY next.config.ts ./
|
|
COPY tsconfig.json ./
|
|
COPY postcss.config.mjs ./
|
|
COPY eslint.config.mjs ./
|
|
COPY prisma ./prisma
|
|
COPY src ./src
|
|
COPY public ./public
|
|
RUN npx prisma generate
|
|
RUN npm run build
|
|
|
|
FROM base AS runner
|
|
WORKDIR /app
|
|
ENV NODE_ENV=production
|
|
|
|
RUN apk add --no-cache openssl wget
|
|
|
|
RUN addgroup --system --gid 1001 nodejs
|
|
RUN adduser --system --uid 1001 nextjs
|
|
|
|
COPY --from=builder /app/public ./public
|
|
COPY --from=builder /app/.next/standalone ./
|
|
COPY --from=builder /app/.next/static ./.next/static
|
|
COPY --from=builder /app/prisma ./prisma
|
|
COPY --from=builder /app/node_modules/.prisma ./node_modules/.prisma
|
|
COPY --from=builder /app/node_modules/@prisma ./node_modules/@prisma
|
|
|
|
COPY scripts/start.sh /app/start.sh
|
|
RUN chmod +x /app/start.sh
|
|
|
|
RUN chown -R nextjs:nodejs /app
|
|
|
|
USER nextjs
|
|
|
|
EXPOSE 3000
|
|
ENV PORT=3000
|
|
ENV HOSTNAME="0.0.0.0"
|
|
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
|
CMD wget --quiet --spider http://localhost:3000/api/check-subdomain?slug=__health || exit 1
|
|
|
|
CMD ["/bin/sh", "/app/start.sh"]
|