Skip to content

Migrate hosting off Vercel → Docker on Oracle Cloud (Dokploy + GHCR)#44

Open
oliverhuangcode wants to merge 1 commit into
mainfrom
deploy/oracle-dokploy-ghcr
Open

Migrate hosting off Vercel → Docker on Oracle Cloud (Dokploy + GHCR)#44
oliverhuangcode wants to merge 1 commit into
mainfrom
deploy/oracle-dokploy-ghcr

Conversation

@oliverhuangcode

Copy link
Copy Markdown

Moves the club's main site off Vercel to a Docker container on the shared Oracle Cloud VM, deployed via Dokploy from a GHCR image built in GitHub Actions. Mirrors the monmap migration, adapted to this repo's stack.

Stack detected

  • Next.js 16 (App Router, React 19), TypeScript, single package (not a monorepo)
  • Package manager: npm (package-lock.json), pinned to npm@11.11.0
  • Needs a Node server at runtime (API routes: Resend email, Sanity revalidate webhook, Instagram, embedded Studio) — not a static export
  • next build is SSG (revalidate = false everywhere + generateStaticParams) → queries the Sanity API at build time

What's here

  • next.config.tsoutput: "standalone"
  • Dockerfile — multi-stage, non-root runtime user, single-package Next standalone shape (no monorepo tracing/transpile). Public NEXT_PUBLIC_SANITY_* are build-args (inlined + read by Studio config); RESEND_API_KEY / SANITY_WEBHOOK_SECRET are runtime-only in Dokploy
  • npm pinned via packageManager + COREPACK_ENABLE_DOWNLOAD_PROMPT=0 so CI resolves the lockfile as generated
  • package-lock.json sync — the committed lockfile was already out of sync (missing encoding/iconv-lite), which would fail npm ci in the image build. Fix adds only those transitive deps + normalization; no version changes
  • .github/workflows/deploy.ymlubuntu-24.04-arm builds linux/arm64, pushes ghcr.io/monashcoding/monashcoding:latest + sha tag, type=gha cache, then POSTs DOKPLOY_DEPLOY_WEBHOOK (self-skips until the secret exists)
  • vercel.json — disables Vercel's GitHub deploy checks
  • docs/deploy.md — Dokploy runbook + apex-domain cutover checklist

Verified locally

  • npm ci succeeds against the synced lockfile
  • tsc --noEmit typecheck passes
  • ⚠️ Full next build not run locally — it's SSG and needs the real Sanity project id + network to prerender (no local .env). First CI run is the fast-feedback gate; the runbook notes this.

Manual follow-ups (can't be done from code — see docs/deploy.md)

  • Set repo Variable NEXT_PUBLIC_SANITY_PROJECT_ID (+ optionally dataset/API version; both have fallbacks)
  • Create the Dokploy app (Docker provider → the GHCR image), set runtime env, port 3000
  • Copy Dokploy's deploy webhook into repo Secret DOKPLOY_DEPLOY_WEBHOOK
  • Make the GHCR package public (or add read creds)
  • Domain (confirmed: both, www→apex redirect): apex monashcoding.com canonical + www 301→apex. Cloudflare A record for apex, grey-cloud first for the LE cert, then orange-cloud
  • Before repointing DNS: verify container healthy in Dokploy + curl -I -H "Host: monashcoding.com" http://localhost on the box (don't swap a working site for a 502)
  • Disconnect Vercel's Git integration in the dashboard, and remove any required "Vercel" status check from the main branch-protection rule

🤖 Generated with Claude Code

Migrate hosting off Vercel to a Docker container on the shared Oracle
Cloud VM, deployed via Dokploy from a GHCR image built in GitHub Actions.
Mirrors the monmap migration, adapted to this repo's stack.

- next.config.ts: output "standalone" for a self-contained server bundle
- Dockerfile: multi-stage, non-root, single-package Next 16 shape. Public
  Sanity vars are build-args (SSG queries Sanity at build); RESEND_API_KEY
  and SANITY_WEBHOOK_SECRET stay runtime-only in Dokploy
- pin npm via packageManager + corepack so CI matches the lockfile
- package-lock.json: sync (adds missing encoding/iconv-lite transitive
  deps) so `npm ci` succeeds in the image build; no version changes
- .github/workflows/deploy.yml: ubuntu-24.04-arm builds linux/arm64,
  pushes ghcr.io/monashcoding/monashcoding:latest + sha, gha cache, then
  POSTs the Dokploy webhook (self-skips until the secret exists)
- vercel.json: disable Vercel's GitHub deploy checks
- docs/deploy.md: Dokploy runbook, build-vs-runtime env, apex cutover

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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