Skip to content

Add Docker support — multi-stage Dockerfile and compose config#30

Open
officialasit wants to merge 1 commit into
mskayyali:mainfrom
officialasit:feat/docker-support
Open

Add Docker support — multi-stage Dockerfile and compose config#30
officialasit wants to merge 1 commit into
mskayyali:mainfrom
officialasit:feat/docker-support

Conversation

@officialasit
Copy link
Copy Markdown

@officialasit officialasit commented Apr 14, 2026

Summary

Lets self-hosters run nodepad with a single docker compose up — no local Node toolchain needed. The container is stateless (notes and AI keys live in the browser's localStorage), so there's nothing to mount, back up, or configure on the server side.

  • Multi-stage Dockerfile (depsbuilderrunner) on node:22-alpine, non-root node user, ~313 MB image
  • output: "standalone" in next.config.mjs for a minimal self-contained server bundle. This is ignored by Vercel's build adapter, so the existing Vercel deployment path is unaffected
  • docker-compose.yml with init: true (tini as PID 1 for correct signal handling) and a node -e 'fetch(...)' healthcheck so the image doesn't need curl/wget
  • HOST_PORT env var to override the host-side port mapping; the container always binds to 3000 internally. .env.example documents it
  • .dockerignore mirroring .gitignore plus build artifacts and local-only files
  • README: new "Run with Docker" subsection under Setup, with an explicit note about the single-replica constraint (see below)

Notes for reviewers

  • Do not scale web beyond 1 replica. proxy.ts uses an in-memory Map as a rate limiter for /api/fetch-url, which assumes a single process. This is called out in both the compose file header and the README.
  • No server-side secrets. The only env vars in .env.example control the container runtime (HOST_PORT). AI provider keys continue to live in localStorage and go directly to the provider.
  • Standalone mode footgun handled: Next's output: "standalone" does not auto-copy public/ or .next/static; the runner stage copies them explicitly.

Test plan

  • docker compose build succeeds on node:22-alpine
  • docker compose up -d — container starts and healthcheck transitions to healthy
  • GET / → 200, HTML served
  • GET /icon.svg → 200 (confirms public/ was copied in standalone mode)
  • cat /proc/1/comm inside container → docker-init (tini is PID 1, signal forwarding works)
  • docker compose down — clean shutdown
  • Reviewer smoke-test: add a note in the browser end-to-end (requires an AI provider key)

🤖 Generated with Claude Code

Self-hosters can now run nodepad end-to-end with `docker compose up`
without touching Node locally.

- Multi-stage Dockerfile (deps → builder → runner) on node:22-alpine,
  non-root `node` user, ~313 MB image
- `output: "standalone"` in next.config.mjs for a minimal server bundle
  (ignored by Vercel, so existing deployment path is unaffected)
- docker-compose.yml with `init: true` for correct signal handling and
  a node-based healthcheck (avoids installing curl in the image)
- HOST_PORT env var to override the host-side port mapping; container
  always binds to 3000 internally
- .dockerignore mirroring .gitignore plus build artifacts
- README: new "Run with Docker" subsection under Setup, noting the
  single-replica constraint from proxy.ts's in-memory rate limiter

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dev-020 added a commit to Dev-020/nodepad_Dev that referenced this pull request May 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant