Skip to content

feat(deploy): containerize the SaaS backend — Dockerfile + compose (slice 9, stacked on #221)#222

Merged
seonghobae merged 3 commits into
feat/saas-predecessorsfrom
feat/saas-deploy
Jul 6, 2026
Merged

feat(deploy): containerize the SaaS backend — Dockerfile + compose (slice 9, stacked on #221)#222
seonghobae merged 3 commits into
feat/saas-predecessorsfrom
feat/saas-deploy

Conversation

@seonghobae

Copy link
Copy Markdown
Contributor

SaaS pivot — slice 9 of N (stacked on #221)

The gap between "built" and "valuable": the backend wasn't deployable. The existing Dockerfile only serves the static client via nginx; the Node backend (auth/cloud/billing) never ran. This makes the full SaaS runnable with one command.

  • Dockerfile.server — Node backend that runs the API and serves the static client from one origin (so the client's default-src 'self' CSP allows the API). Prod deps only (npm ci --omit=dev), non-root (USER node), /data volume for the DB, HEALTHCHECK on /api/health.
  • docker-compose.yml — one-command full stack; SCOPEWEAVE_JWT_SECRET is required (fails fast without it — no insecure default in prod).
  • .dockerignore — keeps node_modules/tests/docs out of the image.
  • docs/deploy.md — env vars, data/scale path (SQLite → Postgres for multi-instance), TLS/proxy, k8s notes.

Verified (podman)

Image builds; container boots (node:sqlite works in node:22-alpine); GET /api/health{ok:true}; signup writes the DB and returns a JWT; static client 200 (index/app.js/analytics.js); data.db blocked 404.

Heads-up (not this PR's code)

The org's trivy-fs check fails repo-wide — it also fails on unrelated PRs (e.g. #213, a UI-only change). Local trivy (vuln+secret+misconfig) and npm audit are clean, and hono is zero-dependency. This is a CI/trivy-version config issue for the maintainer, not a real finding.

🤖 Generated with Claude Code

The #1 gap between built capability and real value: the Node backend wasn't
deployable — the existing Dockerfile only serves the static client via nginx.
Undeployed code has no value; this makes the full SaaS runnable.

- Dockerfile.server: Node backend that runs the API AND serves the static client
  from one origin (satisfies the client's default-src 'self' CSP). Prod deps
  only (npm ci --omit=dev), non-root (USER node), /data volume for the DB,
  HEALTHCHECK on /api/health.
- docker-compose.yml: one-command full stack. SCOPEWEAVE_JWT_SECRET is REQUIRED
  (compose fails fast without it) — no insecure default in prod.
- .dockerignore: keeps node_modules/tests/docs out of the image.
- docs/deploy.md: env vars, data/scale path (SQLite→Postgres for multi-instance),
  TLS/proxy, k8s notes.

Verified with podman: image builds; container boots (node:sqlite works in
node:22-alpine); GET /api/health → {ok:true}; signup writes DB → JWT; static
client 200 (index/app.js/analytics.js); data.db blocked 404.

Note: unrelated to code — the org's `trivy-fs` check currently fails repo-wide
(also on unrelated PRs like #213); local trivy (all scanners) + npm audit are
clean. That's a CI/trivy-version config issue for the maintainer.

Stacked on #221.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018LMoqYsUY6usjNMBjvxCbU
Comment thread Dockerfile.server Fixed
…ies)

Addresses the github-advanced-security review on this PR: node:22-alpine is
now pinned to its sha256 digest (tag kept as a comment for humans).

Verified: podman build succeeds with the pinned ref; the container boots and
/api/health returns ok.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018LMoqYsUY6usjNMBjvxCbU
@seonghobae

Copy link
Copy Markdown
Contributor Author

Addressed the Scorecard Pinned-Dependencies finding: node:22-alpine is now pinned by sha256 digest (02fafea). Verified: podman build with the pinned ref + container boots, /api/health{"ok":true}.

@seonghobae seonghobae merged commit a117dd5 into feat/saas-predecessors Jul 6, 2026
2 checks passed
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.

2 participants