Add self-hosted Docker deployment and GHCR publishing
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
requireAuthmiddleware callsadmin.auth.getUser(token)via the nginx gateway to GoTrue - identical to the hosted Supabase call path. - The schema's
auth.usersreference andauth.uid()RLS function are provided bysupabase/postgres.
Review checklist
-
docker-compose.ymlstarts a fully self-hosted local stack -
docker-compose.prod.ymluses 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-initservice +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.exampleand.env.prod.exampleare 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.