From bbceb864542af1f93c1995825f5b0c887212bf4b Mon Sep 17 00:00:00 2001 From: Joel Martin Date: Tue, 10 Mar 2026 15:34:16 +0000 Subject: [PATCH] feat: add SUPABASE_HOSTNAME env var to override local service host Allows the CLI to work correctly when run inside a dev container with the Docker socket bind-mounted. In that context 127.0.0.1 is the container's own loopback, not the Docker host. Set SUPABASE_HOSTNAME=host.docker.internal to reach sibling containers via Docker Desktop's host gateway without proxying the Docker socket. --- AI assistance: Claude Sonnet 4.6 in Pi Agent - Used to find root cause, propose fix options, draft code/test/docs. - I ran supabase start inside the dev container, confirmed all services healthy, reviewed/edited all code changes/text. --- docs/supabase/start.md | 2 ++ internal/utils/misc.go | 6 ++++++ internal/utils/misc_test.go | 12 ++++++++++++ 3 files changed, 20 insertions(+) diff --git a/docs/supabase/start.md b/docs/supabase/start.md index a590610f11..9a7149eeca 100644 --- a/docs/supabase/start.md +++ b/docs/supabase/start.md @@ -9,3 +9,5 @@ All service containers are started by default. You can exclude those not needed > It is recommended to have at least 7GB of RAM to start all services. Health checks are automatically added to verify the started containers. Use `--ignore-health-check` flag to ignore these errors. + +> If the CLI is running inside a dev container with the Docker socket bind-mounted, set the `SUPABASE_HOSTNAME` environment variable to the hostname reachable from inside that container, such as `host.docker.internal`. diff --git a/internal/utils/misc.go b/internal/utils/misc.go index e08c991a61..7ad493cf06 100644 --- a/internal/utils/misc.go +++ b/internal/utils/misc.go @@ -240,6 +240,12 @@ func ValidateFunctionSlug(slug string) error { } func GetHostname() string { + // Overrides the host for local service connections. Useful when + // running inside a dev container when the Docker host is not + // 127.0.0.1 (container's own loopback). + if h := os.Getenv("SUPABASE_HOSTNAME"); h != "" { + return h + } host := Docker.DaemonHost() if parsed, err := client.ParseHostURL(host); err == nil && parsed.Scheme == "tcp" { if host, _, err := net.SplitHostPort(parsed.Host); err == nil { diff --git a/internal/utils/misc_test.go b/internal/utils/misc_test.go index b12d68c789..b3f5b2d064 100644 --- a/internal/utils/misc_test.go +++ b/internal/utils/misc_test.go @@ -156,6 +156,18 @@ func TestAssertProjectRefIsValid(t *testing.T) { }) } +func TestGetHostname(t *testing.T) { + t.Run("returns SUPABASE_HOSTNAME when set", func(t *testing.T) { + t.Setenv("SUPABASE_HOSTNAME", "host.docker.internal") + assert.Equal(t, "host.docker.internal", GetHostname()) + }) + + t.Run("returns 127.0.0.1 when SUPABASE_HOSTNAME is not set", func(t *testing.T) { + t.Setenv("SUPABASE_HOSTNAME", "") + assert.Equal(t, "127.0.0.1", GetHostname()) + }) +} + func TestWriteFile(t *testing.T) { t.Run("writes file with directories", func(t *testing.T) { fsys := afero.NewMemMapFs()