#3779·atlas

Docker dev database: Atlas dials the host's default gateway instead of loopback for 0.0.0.0-published ports

Author: allanice001Created Aug 20, 2026Updated Aug 22, 2026

Summary

When Atlas provisions its dev database via a docker:// URL, it publishes the container port with an unqualified -p, so Docker reports HostIp: 0.0.0.0. Atlas then appears to resolve 0.0.0.0 to a routable host address and dials the machine's default gateway rather than loopback. On any host whose LAN gateway does not answer on that port, Atlas hangs until it times out:

Error: timeout: postgres: querying system variables: dial tcp 192.168.10.1:32794: connect: operation timed out

192.168.10.1 is my LAN router. The dev container is listening and reachable the whole time — on 127.0.0.1.

This makes atlas migrate diff unusable with the built-in dev database on affected networks, and the error gives no hint that the address is the problem, so it reads as a broken project configuration.

Steps to reproduce

Any config using the built-in dev database is enough:

hcl
data "external_schema" "tenant" {
  program = ["go", "run", "./tools/schema/tenant"]
}

env "tenant" {
  src = data.external_schema.tenant.url
  dev = "docker://postgres/18/dev?search_path=public"
  migration {
    dir    = "file://internal/migrations/tenant"
    format = goose
  }
}
bash
$ atlas migrate validate --env tenant
Error: timeout: postgres: querying system variables: dial tcp 192.168.10.1:32799: connect: operation timed out

It reproduces equally with atlas schema inspect --url "docker://postgres/18/dev?search_path=public", so no project file is required.

Evidence that the port is fine and the address is not

Docker publishes on all interfaces:

bash
$ docker inspect <container> --format '{{json .NetworkSettings.Ports}}'
{"5432/tcp":[{"HostIp":"0.0.0.0","HostPort":"32802"},{"HostIp":"::","HostPort":"32802"}]}

192.168.10.1 is the default gateway, not a Docker address:

bash
$ route -n get default
    gateway: 192.168.10.1
  interface: en6

$ ipconfig getifaddr en0
192.168.10.60

The published port is open on loopback and unreachable on the address Atlas chooses:

bash
$ nc -z -G 5 127.0.0.1 32803
Connection to 127.0.0.1 port 32803 [tcp/*] succeeded!

$ nc -z -G 5 192.168.10.1 32803
(times out)

Expected behaviour

When the published HostIp is 0.0.0.0 (or ::), connect to 127.0.0.1 (or ::1). A wildcard bind means "all interfaces on this host", and loopback is the only one guaranteed to reach the container's published port. Resolving it to the default gateway dials a different machine entirely.

Versions

  • Atlas v1.3.0 (stable release) — reproduces
  • Atlas v1.3.1-2992e0f-canary — reproduces identically

Both were tested on the same machine against the same config, so this is not a regression in the canary build.

  • macOS 15 (Darwin 25.5.0), arm64
  • Docker provided by OrbStack 29.4.0 (Docker API-compatible)
  • Host on a 192.168.10.0/24 LAN, gateway 192.168.10.1

I would expect this to affect any Docker runtime that reports 0.0.0.0 for a published port, which is the default for an unqualified -p. It is likely network-dependent rather than runtime-dependent: on a LAN whose gateway happens to accept connections on the chosen high port, or where the resolution lands elsewhere, the same setup works — which makes it look intermittent across machines and locations.

Workaround

Point ATLAS_DEV_URL (or dev) at a Postgres published explicitly on loopback:

bash
docker run -d --rm --name atlas-dev \
  -e POSTGRES_USER=atlas -e POSTGRES_PASSWORD=atlas -e POSTGRES_DB=atlas \
  -p 127.0.0.1:55999:5432 postgres:18-alpine
export ATLAS_DEV_URL="postgres://atlas:[email protected]:55999/atlas?sslmode=disable&search_path=public"

The docker block would presumably sidestep the URL, but it requires atlas login, so it is not available as a workaround for unauthenticated use.