Files
Cesc 254081462c fix(memory): apply Docker localhost rewrite in embedding provider constructor
Model listing and chat provider construction rewrite localhost to
host.docker.internal via config.DockerLocalhost() when running inside
Docker, but all three memory.NewOpenAIEmbeddingProvider call sites
(verify-embedding handler, runtime memory embedding) passed the raw
api_base through. In Docker the container resolved localhost to itself,
so Ollama Verify Embedding and runtime embedding failed with connection
refused while the model dropdown loaded fine.

Centralize the rewrite inside the constructor so no call site can miss
it, add a SetInDockerForTest hook for environment-independent regression
tests, and pin Docker detection off in httptest-based suites.

Fixes #1519
2026-08-21 10:57:36 +07:00

56 lines
1.5 KiB
Go

package config
import (
"os"
"strings"
"sync"
"sync/atomic"
)
var (
dockerOnce sync.Once
dockerCached bool
// inDockerForTest overrides Docker detection. Production code MUST never
// set this; use SetInDockerForTest exclusively from *_test.go.
inDockerForTest atomic.Pointer[bool]
)
// SetInDockerForTest forces InDocker to return v, bypassing the /.dockerenv
// probe. Returns a restore func that reinstates the previous override (or real
// detection when none was active). Test-only.
func SetInDockerForTest(v bool) func() {
prev := inDockerForTest.Load()
inDockerForTest.Store(&v)
return func() { inDockerForTest.Store(prev) }
}
// InDocker returns true when running inside a Docker container.
// Result is cached after the first call.
func InDocker() bool {
if override := inDockerForTest.Load(); override != nil {
return *override
}
dockerOnce.Do(func() {
_, err := os.Stat("/.dockerenv")
dockerCached = err == nil
})
return dockerCached
}
// DockerLocalhost rewrites localhost or 127.0.0.1 in url to host.docker.internal
// when running inside Docker, so the container can reach host services.
// Returns the url unchanged when not in Docker or when it doesn't reference loopback.
func DockerLocalhost(url string) string {
if !InDocker() {
return url
}
if strings.Contains(url, "localhost") {
return strings.Replace(url, "localhost", "host.docker.internal", 1)
}
if strings.Contains(url, "127.0.0.1") {
return strings.Replace(url, "127.0.0.1", "host.docker.internal", 1)
}
return url
}