Add self-hosted Docker deployment and GHCR publishing

🟢 open · #1 · techieanant/mike ← techieanant/mike · opened 19d ago by Copilot · self · +1,269-14 across 21 files · ↗ on GitHub

From the PR description

Summary

Adds a complete self-hosted Docker deployment setup so Mike can be run with no external Supabase, Postgres, or S3/R2 dependencies.

Changes

New files

File Purpose
backend/Dockerfile Multi-stage build; runtime stage installs LibreOffice for DOC/DOCX → PDF conversion
frontend/Dockerfile Multi-stage build using Next.js standalone output
docker-compose.yml Full local-dev stack (build from source)
docker-compose.prod.yml Production stack using prebuilt GHCR images
.env.example Root-level env template for local dev
.env.prod.example Root-level env template for production
scripts/init-minio.sh One-shot MinIO bucket initialiser
config/nginx.conf Nginx API gateway: routes /auth/v1/ → GoTrue, /rest/v1/ → PostgREST
db/init/30_permissions.sql PostgREST role grants (anon, authenticated, service_role) on public schema
.github/workflows/docker-publish.yml Builds and publishes frontend + backend images to GHCR
docs/local-development.md Local Docker quickstart guide
docs/deployment.md End-to-end production deployment guide

Modified files

File Change
frontend/next.config.ts Added output: "standalone" for efficient Docker builds
README.md Added Docker quickstart section and links to new docs
.gitignore Added !.env.prod.example exception

Stack architecture

Browser ──────────────────────────────────────────┐
                                                   ▼
  frontend :3000  (Next.js)                    kong :8000  (nginx)
       │                                      /auth/v1/ → auth :9999 (GoTrue)
       │  NEXT_PUBLIC_API_BASE_URL            /rest/v1/ → rest :3000 (PostgREST)
       ▼                                           │
  backend :3001  (Express)                         │
       │  SUPABASE_URL=http://kong:8000            ▼
       │  R2_ENDPOINT=http://minio:9000        db :5432  (supabase/postgres)
       ▼
  minio :9000  (object storage)

Auth contract preserved

  • No auth bypass was introduced.
  • The backend's requireAuth middleware calls admin.auth.getUser(token) via the nginx gateway to GoTrue - identical to the hosted Supabase call path.
  • The schema's auth.users reference and auth.uid() RLS function are provided by supabase/postgres.

Review checklist

  • docker-compose.yml starts a fully self-hosted local stack
  • docker-compose.prod.yml uses GHCR images for frontend/backend and does not build locally
  • No auth bypass was introduced
  • Hosted Supabase is no longer required
  • Hosted S3/R2 is no longer required
  • Hosted Postgres is no longer required
  • MinIO bucket init is automated (minio-init service + scripts/init-minio.sh)
  • Postgres schema/bootstrap is automated (mounted into docker-entrypoint-initdb.d/)
  • Backend image includes LibreOffice for DOC/DOCX to PDF conversion
  • GH Actions publishes both frontend and backend images to GHCR
  • .env.example and .env.prod.example are complete and usable
  • Local and production deployment docs are clear and accurate
  • README links to the new docs
  • Production deploy path is documented end-to-end

Our analysis

Self-hosted Docker deployment for Mike — read the full analysis →

Think the analysis missed something the PR description covers?

Capture this PR into my fork

Download a Markdown prompt that tells Claude how to port every commit in this PR into your working tree. Run it via claude -p < capture-pull-1.md from inside the repo you want the changes in.

⬇ Download capture-pull-1.md