next-on-a-stick
v0.1.2
Published
this repo shows one way to deploy a next.js app on docker when the image filesystem is read‑only. the trick is to run the app from a writable directory (`/data`) and keep the image itself immutable.
Downloads
24
Readme
next.js on docker (read‑only filesystem guide)
this repo shows one way to deploy a next.js app on docker when the image filesystem is read‑only. the trick is to run the app from a writable directory (/data) and keep the image itself immutable.
why read‑only matters
- next.js writes at runtime:
.next(build id, cache, isr) needs writes - databases need storage: sqlite file, prisma migrations
- immutable images are safer: fewer surprises; persistent data lives in a volume
dockerfile ❓
the dockerfile uses a 3‑stage build to keep the final image small and secure:
deps (install dependencies)
- picks your package manager based on the lockfile
- installs production deps in a clean layer
builder (compile app)
- copies source
- runs
npx prisma generate(so prisma client matches your schema) - builds next.js with
output: "standalone"so the server can run without the whole repo
runner (minimal runtime)
- creates a non‑root user
nextjs - prepares a writable directory
/data/.next - copies built bits:
/.next/standalone→/app/standalone(server code)/.next→/app/next_build(full build artifacts)/node_modules→/app/node_modules(fallback if standalone misses anything)
- sets runtime envs
PORT=8080,HOSTNAME=0.0.0.0, and a defaultDATABASE_URL=file:/data/database.db - switches to user
nextjs, setsWORKDIR /data, and delegates startup to the entrypoint
- creates a non‑root user
the container exposes port 8080 and starts with node server.js (after the entrypoint finishes preparing files in /data).
entrypoint ❓
the script docker-entrypoint.sh makes sure everything the app needs is in a writable place:
- creates
/data/.next(writable) - on first run (no
/data/server.jsyet):- copies the standalone app from
/app/standaloneto/data - copies
public/andprisma/so they’re available at runtime - if needed, copies the full
/app/node_modulesinto/data(standalone fallback, prisma binaries, etc.)
- copies the standalone app from
- syncs build artifacts: copies
/app/next_build→/data/.nextif newer or missing - checks required files exist:
server.jsand.next/BUILD_ID - finally
execs the container command (node server.js), inheriting signals properly
result: the app actually runs from /data (a volume), while the image stays read‑only.
npx next-on-a-stick
run this helper inside an existing next.js project to drop in the docker/read‑only scaffolding from this repo:
npx next-on-a-stickwhat it does:
- creates/updates
Dockerfile,.dockerignore, anddocker-entrypoint.sh - patches
next.config.*sooutput: "standalone"+images.unoptimized+outputFileTracingRoot - keeps your files unless you pass
--force(try--dry-runto preview changes)
options:
npx next-on-a-stick --dry-run # print the plan without touching files
npx next-on-a-stick --force # overwrite existing files
npx next-on-a-stick --cwd ./path # run against another folderafter it runs, build the image with docker build -t my-app ..
environment
DATABASE_URL→ usefile:/data/database.dbfor sqlite stored in the mounted/datavolumePORT→ defaults to8080in the image
set envs with -e VAR=value on docker run or via your orchestrator.
prisma and migrations (optional)
the entrypoint includes a commented example to run prisma at startup. if you want automatic schema sync:
- uncomment the lines in
docker-entrypoint.shthat runprisma db push - ensure
node_modules/.bin/prismais available in/data(the script already copies required prisma bits if needed)
for manual runs:
docker exec -it <container-id> sh -lc "./node_modules/.bin/prisma db push"troubleshooting
cannot find module 'next'
- the entrypoint copies full
node_modulesinto/dataif the standalone bundle is missing something
- the entrypoint copies full
read‑only file system
- the app runs from
/data. don’t override the entrypoint; mount a volume to/dataif you need persistence
- the app runs from
404 on routes
- ensure
.nextartifacts are present under/data/.next(the entrypoint copies from/app/next_build)
- ensure
todo
- this project still NEEDS to be TESTED properly and thoroughly
- check node_modules copying
- prisma migrations are basically untested
notes
- the image uses a non-root user and a writable volume to keep runtime safe and predictable
- next.js standalone output plus a tiny entrypoint is a good fit for immutable images
- PLEASE REPORT ALL ISSUES
