docker-compose.yml 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. x-logging: &default-logging
  2. driver: json-file
  3. options:
  4. max-size: "10m"
  5. max-file: "5"
  6. services:
  7. # ─── Next.js Application ──────────────────────────────────────────
  8. app:
  9. build:
  10. context: .
  11. dockerfile: Dockerfile
  12. restart: unless-stopped
  13. logging: *default-logging
  14. depends_on:
  15. supabase-kong:
  16. condition: service_started
  17. environment:
  18. - TMDB_API_KEY=${TMDB_API_KEY}
  19. - NEXT_PUBLIC_SUPABASE_URL=${NEXT_PUBLIC_SUPABASE_URL}
  20. - NEXT_PUBLIC_SUPABASE_ANON_KEY=${ANON_KEY}
  21. - SUPABASE_INTERNAL_URL=http://supabase-kong:8000
  22. - SUPABASE_SERVICE_ROLE_KEY=${SERVICE_ROLE_KEY}
  23. - MASTER_ADMIN_USERNAME=${MASTER_ADMIN_USERNAME}
  24. - MASTER_ADMIN_TOTP_SECRET=${MASTER_ADMIN_TOTP_SECRET}
  25. - IRON_SESSION_SECRET=${IRON_SESSION_SECRET}
  26. networks:
  27. - internal
  28. # ─── Caddy Reverse Proxy ──────────────────────────────────────────
  29. caddy:
  30. image: caddy:2-alpine
  31. restart: unless-stopped
  32. logging: *default-logging
  33. ports:
  34. - "80:80"
  35. - "443:443"
  36. - "443:443/udp"
  37. environment:
  38. - DOMAIN=${DOMAIN:-localhost}
  39. - TLS_EMAIL=${TLS_EMAIL:-}
  40. volumes:
  41. - ./Caddyfile:/etc/caddy/Caddyfile:ro
  42. - caddy_data:/data
  43. - caddy_config:/config
  44. depends_on:
  45. - app
  46. networks:
  47. - internal
  48. # ─── Supabase: Postgres ───────────────────────────────────────────
  49. supabase-db:
  50. image: supabase/postgres:15.8.1.060
  51. restart: unless-stopped
  52. logging: *default-logging
  53. healthcheck:
  54. test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-supabase_admin} -d ${POSTGRES_DB:-supabase}"]
  55. interval: 10s
  56. timeout: 5s
  57. retries: 5
  58. environment:
  59. POSTGRES_USER: ${POSTGRES_USER:-supabase_admin}
  60. POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
  61. POSTGRES_DB: ${POSTGRES_DB:-supabase}
  62. JWT_SECRET: ${JWT_SECRET}
  63. volumes:
  64. - supabase_db:/var/lib/postgresql/data
  65. networks:
  66. - internal
  67. # ─── Supabase: GoTrue (Auth) ──────────────────────────────────────
  68. supabase-auth:
  69. image: supabase/gotrue:v2.170.0
  70. restart: unless-stopped
  71. logging: *default-logging
  72. depends_on:
  73. supabase-db:
  74. condition: service_healthy
  75. environment:
  76. GOTRUE_API_HOST: "0.0.0.0"
  77. GOTRUE_API_PORT: "9999"
  78. API_EXTERNAL_URL: ${NEXT_PUBLIC_SUPABASE_URL}
  79. GOTRUE_DB_DRIVER: postgres
  80. GOTRUE_DB_DATABASE_URL: postgres://${POSTGRES_USER:-supabase_admin}:${POSTGRES_PASSWORD}@supabase-db:5432/${POSTGRES_DB:-supabase}?search_path=auth
  81. GOTRUE_SITE_URL: ${SITE_URL:-http://localhost:3000}
  82. GOTRUE_URI_ALLOW_LIST: ""
  83. GOTRUE_DISABLE_SIGNUP: "false"
  84. GOTRUE_JWT_SECRET: ${JWT_SECRET}
  85. GOTRUE_JWT_EXP: "3600"
  86. GOTRUE_JWT_DEFAULT_GROUP_NAME: authenticated
  87. # Anonymous auth enabled — core requirement
  88. GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED: "true"
  89. # Disable all other auth methods
  90. GOTRUE_EXTERNAL_EMAIL_ENABLED: "false"
  91. GOTRUE_EXTERNAL_PHONE_ENABLED: "false"
  92. GOTRUE_MAILER_AUTOCONFIRM: "false"
  93. GOTRUE_SMS_AUTOCONFIRM: "false"
  94. networks:
  95. - internal
  96. # ─── Supabase: PostgREST ──────────────────────────────────────────
  97. supabase-rest:
  98. image: postgrest/postgrest:v12.2.8
  99. restart: unless-stopped
  100. logging: *default-logging
  101. depends_on:
  102. supabase-db:
  103. condition: service_healthy
  104. environment:
  105. PGRST_DB_URI: postgres://${POSTGRES_USER:-supabase_admin}:${POSTGRES_PASSWORD}@supabase-db:5432/${POSTGRES_DB:-supabase}
  106. PGRST_DB_SCHEMAS: public
  107. PGRST_DB_ANON_ROLE: anon
  108. PGRST_JWT_SECRET: ${JWT_SECRET}
  109. PGRST_DB_USE_LEGACY_GUCS: "false"
  110. networks:
  111. - internal
  112. # ─── Supabase: Realtime ───────────────────────────────────────────
  113. supabase-realtime:
  114. image: supabase/realtime:v2.34.47
  115. restart: unless-stopped
  116. logging: *default-logging
  117. depends_on:
  118. supabase-db:
  119. condition: service_healthy
  120. environment:
  121. PORT: "4000"
  122. DB_HOST: supabase-db
  123. DB_PORT: "5432"
  124. DB_USER: ${POSTGRES_USER:-supabase_admin}
  125. DB_PASSWORD: ${POSTGRES_PASSWORD}
  126. DB_NAME: ${POSTGRES_DB:-supabase}
  127. DB_AFTER_CONNECT_QUERY: "SET search_path TO _realtime"
  128. DB_ENC_KEY: supabaserealtime
  129. API_JWT_SECRET: ${JWT_SECRET}
  130. SECRET_KEY_BASE: ${REALTIME_SECRET_KEY_BASE:-please-generate-a-64-char-secret-key-base-for-realtime-service!!}
  131. ERL_AFLAGS: "-proto_dist inet_tcp"
  132. DNS_NODES: "''"
  133. RLIMIT_NOFILE: "10000"
  134. APP_NAME: realtime
  135. SEED_SELF_HOST: "true"
  136. networks:
  137. - internal
  138. # ─── Supabase: Kong (API Gateway) ─────────────────────────────────
  139. supabase-kong:
  140. image: kong:2.8.1
  141. restart: unless-stopped
  142. logging: *default-logging
  143. depends_on:
  144. - supabase-auth
  145. - supabase-rest
  146. - supabase-realtime
  147. environment:
  148. KONG_DATABASE: "off"
  149. KONG_DECLARATIVE_CONFIG: /var/lib/kong/kong.yml
  150. KONG_DNS_ORDER: LAST,A,CNAME
  151. KONG_PLUGINS: request-transformer,cors,key-auth,acl
  152. KONG_NGINX_PROXY_PROXY_BUFFER_SIZE: 160k
  153. KONG_NGINX_PROXY_PROXY_BUFFERS: 64 160k
  154. ANON_KEY: ${ANON_KEY}
  155. SERVICE_ROLE_KEY: ${SERVICE_ROLE_KEY}
  156. volumes:
  157. - ./supabase/kong/kong.yml:/var/lib/kong/kong.yml:ro
  158. networks:
  159. - internal
  160. # ─── Supabase: Studio (dev only) ──────────────────────────────────
  161. supabase-studio:
  162. image: supabase/studio:20250317-b9tried
  163. restart: unless-stopped
  164. logging: *default-logging
  165. ports:
  166. - "127.0.0.1:3001:3000"
  167. depends_on:
  168. - supabase-kong
  169. environment:
  170. STUDIO_PG_META_URL: http://supabase-meta:8080
  171. POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
  172. SUPABASE_URL: http://supabase-kong:8000
  173. SUPABASE_REST_URL: http://supabase-kong:8000/rest/v1/
  174. SUPABASE_ANON_KEY: ${ANON_KEY}
  175. SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY}
  176. DEFAULT_ORGANIZATION_NAME: MovieDice
  177. DEFAULT_PROJECT_NAME: MovieDice
  178. NEXT_PUBLIC_ENABLE_LOGS: "true"
  179. NEXT_ANALYTICS_BACKEND_PROVIDER: postgres
  180. networks:
  181. - internal
  182. # ─── Supabase: pg_meta (required by Studio) ───────────────────────
  183. supabase-meta:
  184. image: supabase/postgres-meta:v0.84.2
  185. restart: unless-stopped
  186. logging: *default-logging
  187. depends_on:
  188. supabase-db:
  189. condition: service_healthy
  190. environment:
  191. PG_META_PORT: "8080"
  192. PG_META_DB_HOST: supabase-db
  193. PG_META_DB_PORT: "5432"
  194. PG_META_DB_NAME: ${POSTGRES_DB:-supabase}
  195. PG_META_DB_USER: ${POSTGRES_USER:-supabase_admin}
  196. PG_META_DB_PASSWORD: ${POSTGRES_PASSWORD}
  197. networks:
  198. - internal
  199. # ─── Cron Service ─────────────────────────────────────────────────
  200. cron:
  201. build:
  202. context: ./cron
  203. dockerfile: Dockerfile
  204. restart: unless-stopped
  205. logging: *default-logging
  206. depends_on:
  207. supabase-kong:
  208. condition: service_started
  209. environment:
  210. - SUPABASE_URL=http://supabase-kong:8000
  211. - SUPABASE_SERVICE_ROLE_KEY=${SERVICE_ROLE_KEY}
  212. - TMDB_API_KEY=${TMDB_API_KEY}
  213. networks:
  214. - internal
  215. # ─── Database Backup ──────────────────────────────────────────────
  216. backup:
  217. image: postgres:15-alpine
  218. restart: "no"
  219. logging: *default-logging
  220. depends_on:
  221. supabase-db:
  222. condition: service_healthy
  223. environment:
  224. POSTGRES_USER: ${POSTGRES_USER:-supabase_admin}
  225. POSTGRES_DB: ${POSTGRES_DB:-supabase}
  226. PGPASSWORD: ${POSTGRES_PASSWORD}
  227. volumes:
  228. - ./backup/backup.sh:/backup.sh:ro
  229. - supabase_backups:/backups
  230. entrypoint: ["/bin/sh", "/backup.sh"]
  231. networks:
  232. - internal
  233. profiles:
  234. - backup
  235. volumes:
  236. supabase_db:
  237. supabase_backups:
  238. caddy_data:
  239. caddy_config:
  240. networks:
  241. internal:
  242. driver: bridge