From c9113c9293fbd961bd08d19374957a2d740b46c4 Mon Sep 17 00:00:00 2001 From: admin Date: Fri, 12 Dec 2025 10:42:06 +0100 Subject: [PATCH] Add Supabase docker-compose.yml --- supabase/docker-compose.yml | 368 ++++++++++++++++++++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 supabase/docker-compose.yml diff --git a/supabase/docker-compose.yml b/supabase/docker-compose.yml new file mode 100644 index 0000000..4665e28 --- /dev/null +++ b/supabase/docker-compose.yml @@ -0,0 +1,368 @@ +version: "3.8" + +services: + # =========================================== + # DATABASE + # =========================================== + supabase-db: + image: supabase/postgres:15.8.1.21 + container_name: supabase-db + restart: unless-stopped + healthcheck: + test: ["CMD", "pg_isready", "-U", "postgres", "-h", "localhost"] + interval: 5s + timeout: 5s + retries: 10 + command: + - postgres + - -c + - config_file=/etc/postgresql/postgresql.conf + - -c + - log_min_messages=fatal + environment: + POSTGRES_HOST: /var/run/postgresql + PGPORT: ${POSTGRES_PORT:-5432} + POSTGRES_PORT: ${POSTGRES_PORT:-5432} + PGPASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + PGDATABASE: ${POSTGRES_DB:-postgres} + POSTGRES_DB: ${POSTGRES_DB:-postgres} + JWT_SECRET: ${JWT_SECRET} + JWT_EXP: ${JWT_EXPIRY:-3600} + volumes: + - supabase_db_data:/var/lib/postgresql/data:Z + networks: + - supabase-internal + - dokploy-network + + # =========================================== + # API GATEWAY (KONG) + # =========================================== + supabase-kong: + image: kong:2.8.1 + container_name: supabase-kong + restart: unless-stopped + depends_on: + supabase-analytics: + condition: service_healthy + entrypoint: bash -c 'eval "echo \"$$(cat ~/temp.yml)\"" > ~/kong.yml && /docker-entrypoint.sh kong docker-start' + environment: + KONG_DATABASE: "off" + KONG_DECLARATIVE_CONFIG: /home/kong/kong.yml + KONG_DNS_ORDER: LAST,A,CNAME + KONG_PLUGINS: request-transformer,cors,key-auth,acl,basic-auth + KONG_NGINX_PROXY_PROXY_BUFFER_SIZE: 160k + KONG_NGINX_PROXY_PROXY_BUFFERS: 64 160k + SUPABASE_ANON_KEY: ${ANON_KEY} + SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY} + DASHBOARD_USERNAME: ${DASHBOARD_USERNAME} + DASHBOARD_PASSWORD: ${DASHBOARD_PASSWORD} + volumes: + - ./volumes/api/kong.yml:/home/kong/temp.yml:ro + networks: + - supabase-internal + - dokploy-network + labels: + - "traefik.enable=true" + - "traefik.http.routers.supabase-api.rule=Host(`supabase.mylder.io`)" + - "traefik.http.routers.supabase-api.entrypoints=websecure" + - "traefik.http.routers.supabase-api.tls.certResolver=letsencrypt" + - "traefik.http.services.supabase-api.loadbalancer.server.port=8000" + - "traefik.docker.network=dokploy-network" + + # =========================================== + # AUTHENTICATION (GOTRUE) + # =========================================== + supabase-auth: + image: supabase/gotrue:v2.172.0 + container_name: supabase-auth + restart: unless-stopped + depends_on: + supabase-db: + condition: service_healthy + supabase-analytics: + condition: service_healthy + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9999/health"] + interval: 5s + timeout: 5s + retries: 3 + environment: + GOTRUE_API_HOST: 0.0.0.0 + GOTRUE_API_PORT: 9999 + API_EXTERNAL_URL: ${API_EXTERNAL_URL} + GOTRUE_DB_DRIVER: postgres + GOTRUE_DB_DATABASE_URL: postgres://supabase_auth_admin:${POSTGRES_PASSWORD}@supabase-db:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-postgres} + GOTRUE_SITE_URL: ${SITE_URL} + GOTRUE_URI_ALLOW_LIST: ${ADDITIONAL_REDIRECT_URLS} + GOTRUE_DISABLE_SIGNUP: ${DISABLE_SIGNUP:-false} + GOTRUE_JWT_ADMIN_ROLES: service_role + GOTRUE_JWT_AUD: authenticated + GOTRUE_JWT_DEFAULT_GROUP_NAME: authenticated + GOTRUE_JWT_EXP: ${JWT_EXPIRY:-3600} + GOTRUE_JWT_SECRET: ${JWT_SECRET} + GOTRUE_EXTERNAL_EMAIL_ENABLED: ${ENABLE_EMAIL_SIGNUP:-true} + GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED: ${ENABLE_ANONYMOUS_SIGN_INS:-false} + GOTRUE_MAILER_AUTOCONFIRM: ${ENABLE_EMAIL_AUTOCONFIRM:-false} + GOTRUE_SMTP_ADMIN_EMAIL: ${SMTP_ADMIN_EMAIL} + GOTRUE_SMTP_HOST: ${SMTP_HOST} + GOTRUE_SMTP_PORT: ${SMTP_PORT:-587} + GOTRUE_SMTP_USER: ${SMTP_USER} + GOTRUE_SMTP_PASS: ${SMTP_PASS} + GOTRUE_SMTP_SENDER_NAME: ${SMTP_SENDER_NAME:-Mylder} + GOTRUE_MAILER_URLPATHS_INVITE: ${MAILER_URLPATHS_INVITE:-/auth/v1/verify} + GOTRUE_MAILER_URLPATHS_CONFIRMATION: ${MAILER_URLPATHS_CONFIRMATION:-/auth/v1/verify} + GOTRUE_MAILER_URLPATHS_RECOVERY: ${MAILER_URLPATHS_RECOVERY:-/auth/v1/verify} + GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE: ${MAILER_URLPATHS_EMAIL_CHANGE:-/auth/v1/verify} + GOTRUE_EXTERNAL_PHONE_ENABLED: ${ENABLE_PHONE_SIGNUP:-false} + GOTRUE_SMS_AUTOCONFIRM: ${ENABLE_PHONE_AUTOCONFIRM:-false} + networks: + - supabase-internal + + # =========================================== + # REST API (POSTGREST) + # =========================================== + supabase-rest: + image: postgrest/postgrest:v12.2.0 + container_name: supabase-rest + restart: unless-stopped + depends_on: + supabase-db: + condition: service_healthy + supabase-analytics: + condition: service_healthy + environment: + PGRST_DB_URI: postgres://authenticator:${POSTGRES_PASSWORD}@supabase-db:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-postgres} + PGRST_DB_SCHEMAS: ${PGRST_DB_SCHEMAS:-public,storage,graphql_public} + PGRST_DB_ANON_ROLE: anon + PGRST_JWT_SECRET: ${JWT_SECRET} + PGRST_DB_USE_LEGACY_GUCS: "false" + PGRST_APP_SETTINGS_JWT_SECRET: ${JWT_SECRET} + PGRST_APP_SETTINGS_JWT_EXP: ${JWT_EXPIRY:-3600} + command: "postgrest" + networks: + - supabase-internal + + # =========================================== + # REALTIME + # =========================================== + supabase-realtime: + image: supabase/realtime:v2.68.0 + container_name: supabase-realtime + restart: unless-stopped + depends_on: + supabase-db: + condition: service_healthy + supabase-analytics: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-sSfL", "--head", "-o", "/dev/null", "http://localhost:4000/api/health"] + interval: 10s + timeout: 5s + retries: 5 + environment: + PORT: 4000 + DB_HOST: supabase-db + DB_PORT: ${POSTGRES_PORT:-5432} + DB_USER: supabase_admin + DB_PASSWORD: ${POSTGRES_PASSWORD} + DB_NAME: ${POSTGRES_DB:-postgres} + DB_AFTER_CONNECT_QUERY: 'SET search_path TO _realtime' + DB_ENC_KEY: ${VAULT_ENC_KEY} + API_JWT_SECRET: ${JWT_SECRET} + SECRET_KEY_BASE: ${SECRET_KEY_BASE} + ERL_AFLAGS: -proto_dist inet_tcp + DNS_NODES: "''" + RLIMIT_NOFILE: "10000" + APP_NAME: realtime + SEED_SELF_HOST: "true" + RUN_JANITOR: "true" + command: > + bash -c "/app/bin/migrate && /app/bin/realtime eval 'Realtime.Release.seeds(Realtime.Repo)' && /app/bin/server" + networks: + - supabase-internal + + # =========================================== + # STORAGE + # =========================================== + supabase-storage: + image: supabase/storage-api:v1.17.0 + container_name: supabase-storage + restart: unless-stopped + depends_on: + supabase-db: + condition: service_healthy + supabase-rest: + condition: service_started + supabase-imgproxy: + condition: service_started + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5000/status"] + interval: 5s + timeout: 5s + retries: 3 + environment: + ANON_KEY: ${ANON_KEY} + SERVICE_KEY: ${SERVICE_ROLE_KEY} + POSTGREST_URL: http://supabase-rest:3000 + PGRST_JWT_SECRET: ${JWT_SECRET} + DATABASE_URL: postgres://supabase_storage_admin:${POSTGRES_PASSWORD}@supabase-db:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-postgres} + FILE_SIZE_LIMIT: 52428800 + STORAGE_BACKEND: file + FILE_STORAGE_BACKEND_PATH: /var/lib/storage + TENANT_ID: stub + REGION: local + GLOBAL_S3_BUCKET: stub + ENABLE_IMAGE_TRANSFORMATION: "true" + IMGPROXY_URL: http://supabase-imgproxy:5001 + volumes: + - supabase_storage_data:/var/lib/storage:z + networks: + - supabase-internal + + # =========================================== + # IMAGE PROXY + # =========================================== + supabase-imgproxy: + image: darthsim/imgproxy:v3.8.0 + container_name: supabase-imgproxy + restart: unless-stopped + healthcheck: + test: ["CMD", "imgproxy", "health"] + interval: 5s + timeout: 5s + retries: 3 + environment: + IMGPROXY_BIND: ":5001" + IMGPROXY_LOCAL_FILESYSTEM_ROOT: / + IMGPROXY_USE_ETAG: "true" + IMGPROXY_ENABLE_WEBP_DETECTION: ${IMGPROXY_ENABLE_WEBP_DETECTION:-true} + volumes: + - supabase_storage_data:/var/lib/storage:z + networks: + - supabase-internal + + # =========================================== + # META (PG-META) + # =========================================== + supabase-meta: + image: supabase/postgres-meta:v0.89.0 + container_name: supabase-meta + restart: unless-stopped + depends_on: + supabase-db: + condition: service_healthy + supabase-analytics: + condition: service_healthy + environment: + PG_META_PORT: 8080 + PG_META_HOST: 0.0.0.0 + PG_META_DB_HOST: supabase-db + PG_META_DB_PORT: ${POSTGRES_PORT:-5432} + PG_META_DB_NAME: ${POSTGRES_DB:-postgres} + PG_META_DB_USER: supabase_admin + PG_META_DB_PASSWORD: ${POSTGRES_PASSWORD} + PG_META_CRYPTO_KEY: ${PG_META_CRYPTO_KEY} + networks: + - supabase-internal + + # =========================================== + # EDGE FUNCTIONS + # =========================================== + supabase-functions: + image: supabase/edge-runtime:v1.69.0 + container_name: supabase-functions + restart: unless-stopped + depends_on: + supabase-analytics: + condition: service_healthy + environment: + JWT_SECRET: ${JWT_SECRET} + SUPABASE_URL: http://supabase-kong:8000 + SUPABASE_ANON_KEY: ${ANON_KEY} + SUPABASE_SERVICE_ROLE_KEY: ${SERVICE_ROLE_KEY} + SUPABASE_DB_URL: postgresql://postgres:${POSTGRES_PASSWORD}@supabase-db:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-postgres} + VERIFY_JWT: ${FUNCTIONS_VERIFY_JWT:-true} + volumes: + - ./volumes/functions:/home/deno/functions:Z + command: + - start + - --main-service + - /home/deno/functions/main + networks: + - supabase-internal + + # =========================================== + # ANALYTICS (LOGFLARE) + # =========================================== + supabase-analytics: + image: supabase/logflare:1.12.0 + container_name: supabase-analytics + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-sSfL", "--head", "-o", "/dev/null", "http://localhost:4000/health"] + interval: 5s + timeout: 5s + retries: 10 + depends_on: + supabase-db: + condition: service_healthy + environment: + LOGFLARE_SINGLE_TENANT: "true" + LOGFLARE_SUPABASE_MODE: "true" + LOGFLARE_NODE_HOST: 127.0.0.1 + DB_USERNAME: supabase_admin + DB_DATABASE: ${POSTGRES_DB:-postgres} + DB_HOSTNAME: supabase-db + DB_PORT: ${POSTGRES_PORT:-5432} + DB_PASSWORD: ${POSTGRES_PASSWORD} + DB_SCHEMA: _analytics + LOGFLARE_API_KEY: ${LOGFLARE_API_KEY} + POSTGRES_BACKEND_URL: postgresql://supabase_admin:${POSTGRES_PASSWORD}@supabase-db:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-postgres} + POSTGRES_BACKEND_SCHEMA: _analytics + LOGFLARE_FEATURE_FLAG_OVERRIDE: multibackend=true + networks: + - supabase-internal + + # =========================================== + # STUDIO (DASHBOARD) + # =========================================== + supabase-studio: + image: supabase/studio:2024.12.02-sha-8fac0a1 + container_name: supabase-studio + restart: unless-stopped + healthcheck: + test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/api/platform/health', (r) => process.exit(r.statusCode !== 200 ? 1 : 0)).on('error', () => process.exit(1))"] + interval: 5s + timeout: 5s + retries: 3 + depends_on: + supabase-analytics: + condition: service_healthy + environment: + STUDIO_PG_META_URL: http://supabase-meta:8080 + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + DEFAULT_ORGANIZATION_NAME: ${STUDIO_DEFAULT_ORGANIZATION:-Mylder} + DEFAULT_PROJECT_NAME: ${STUDIO_DEFAULT_PROJECT:-Main} + SUPABASE_URL: http://supabase-kong:8000 + SUPABASE_PUBLIC_URL: ${SUPABASE_PUBLIC_URL} + SUPABASE_ANON_KEY: ${ANON_KEY} + SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY} + AUTH_JWT_SECRET: ${JWT_SECRET} + LOGFLARE_API_KEY: ${LOGFLARE_API_KEY} + LOGFLARE_URL: http://supabase-analytics:4000 + NEXT_PUBLIC_ENABLE_LOGS: "true" + NEXT_ANALYTICS_BACKEND_PROVIDER: postgres + networks: + - supabase-internal + +networks: + supabase-internal: + name: supabase-internal + driver: bridge + dokploy-network: + external: true + +volumes: + supabase_db_data: + supabase_storage_data: