The postinstall hook runs scripts/patch-next-dev-blocker.cjs, but at that point in the Docker build only package.json and package-lock.json have been copied — the scripts/ directory isn't there yet, so the hook fails with MODULE_NOT_FOUND. The patch is dev-only (it mutates Next 16's dev-only cross-site guard, which is never loaded in production), so it's safe to skip during the Docker build. Two changes: 1. Dockerfile: use 'npm ci --ignore-scripts' in the deps stage so the postinstall hook doesn't run before the scripts/ directory is available. 2. scripts/patch-next-dev-blocker.cjs: bail out cleanly with exit 0 when node_modules/next is missing, so the script is also safe to run in any intermediate state.
3.4 KiB
Deploying to Coolify
This project ships with a Dockerfile and a docker-compose.yml that
work with Coolify v4 out of the box.
Quick start
-
Create a new Application in Coolify
- Source: Git Repository
- Repository URL:
http://forgejo-b82b4lpyyzyg40thdsjdd38i.163.245.214.68.sslip.io/David/MEGAINFRA-WEBAPP.git - Branch:
main - Build Pack:
Dockerfile - Port:
3000
-
Set the environment variables (Coolify → Application → Environment Variables):
Key Value Notes NEXT_PUBLIC_APP_PIN2468The PIN the login screen accepts. Change this in production. NEXT_PUBLIC_APP_NAMEMEGA INFRASTRUCTUREShown on the lock screen. NEXT_PUBLIC_DEFAULT_THEMElightlightordark. -
Expose the port — Coolify's Traefik will route traffic to the container on port 3000. The server binds to
0.0.0.0so it accepts connections from any host. -
Healthcheck —
GET /api/healthreturns a 200 JSON payload with the live counts and is wired as the DockerHEALTHCHECK.
What the Dockerfile does
- Multi-stage build: it caches
npm ciseparately from the source copy, so unchanged dependencies don't invalidate the build layer. - Next.js standalone output: with
output: "standalone"innext.config.js, the build produces a self-contained.next/standalone/directory with a trimmednode_modulesand aserver.jsentry point. - Non-root runtime: the server runs as a dedicated
nextjsuser. - PWA service worker:
next buildregeneratespublic/sw.js,public/workbox-*.jsandpublic/manifest.jsonfrom the@ducanh2912/next-pwaplugin. The.dockerignoredeliberately excludes the pre-built versions so the build always ships the right hashes for the new release.
Build-time concern: the dev-only patch
scripts/patch-next-dev-blocker.cjs patches Next 16's dev-only
cross-site guard so next dev accepts requests from any host (LAN,
tunneled domains, etc.). The patched module is only loaded by
next dev — never by the production server — so the Dockerfile runs
npm ci --ignore-scripts in the deps stage to skip the postinstall
hook entirely. The patch script is also self-resilient: it detects
when node_modules/next is absent and exits 0 cleanly.
Environment variables
Anything prefixed with NEXT_PUBLIC_ is inlined into the client bundle
at build time. If you change NEXT_PUBLIC_APP_PIN, you must rebuild
the image — Coolify will not pick up the change otherwise.
| Variable | Required | Default | Purpose |
|---|---|---|---|
NEXT_PUBLIC_APP_PIN |
Yes | 2468 |
Login PIN. |
NEXT_PUBLIC_APP_NAME |
No | MEGA INFRASTRUCTURE |
Brand name on the lock screen. |
NEXT_PUBLIC_DEFAULT_THEME |
No | light |
Default theme before user preference is read from localStorage. |
NEXT_PUBLIC_API_BASE_URL |
No | unset | When you wire PocketBase, point this at the backend. |
POCKETBASE_URL |
No | unset | Backend URL for server-side requests. |
POCKETBASE_TOKEN |
No | unset | Server-side auth token. |
Useful Coolify probes
| Probe | URL | Expects |
|---|---|---|
| Liveness | GET /api/health |
200 with JSON body |
| Auth gate | GET /login |
200 HTML |
Local smoke test
docker compose up --build
# wait ~2 minutes for the first build
open http://localhost:3000/login
# default PIN: 2468