Docker and external services
devhost can give a Docker container, or any server something else runs, an HTTPS hostname. It routes to a port published on this machine; it cannot reach container names or addresses inside a Docker network.
Route a container that Docker runs
Section titled “Route a container that Docker runs”Publish the container’s port on the host, for example ports: ["4100:4100"] in Compose, then declare the service as external with managed = false:
[services.preview]managed = falseport = 4100host = "preview.hello.localhost"devhost claims the hostname and port, waits until the port accepts connections, and routes to it. It never starts, stops, or restarts the container.
- An external service cannot have a
command,injectPort, orport = "auto"; routing it takes a fixedport. - Its health check can be the default TCP check, an explicit
tcpport, or anhttpURL, but notprocess, since devhost owns no process for it. - The Services panel tags it
externaland offers no restart; recover it outside devhost. - A repository that contains an external service cannot switch worktrees.
To start the container from another service of the stack, add that service to dependsOn:
[services.infra]command = ["bun", "run", "dev:infra"] # starts the containershealth = { process = true }
[services.preview]managed = falsedependsOn = ["infra"]port = 4100host = "preview.hello.localhost"Let devhost run Compose
Section titled “Let devhost run Compose”When devhost should start and stop the container itself, make it an ordinary service whose command runs Compose in the foreground:
[services.api]command = ["docker", "compose", "up", "--build", "api"]port = 4000host = "api.hello.localhost"health = { http = "http://127.0.0.1:4000/healthz" }This works because Compose publishes 4000:4000 on the host. Health URLs must use 127.0.0.1, localhost, or ::1; a Docker-internal name such as http://api:4000 is rejected.