Docker & ContainersXXVI Β· DNS & Service DiscoveryService identity
Names, aliases, and what breaks when they change
What you'll learn
- Distinguish container name, hostname, network alias and Compose service name
- Predict which names survive a rename, a recreate and a network change
- Configure a reverse proxy so it re-resolves an upstream that moved
Prerequisites
Verified against Docker Engine 29.x Β· Docker Engine 28.x Β· Docker Compose 2.x Β· containerd 2.x Β· runc 1.2.x Β· BuildKit 0.20+ Β· Linux kernel 5.15+ Β· Ubuntu 24.04 LTS Β· Debian 12 (Bookworm) Β· 2026-08-11
A container does not have βa nameβ. It has several, they come from different places, they are scoped differently, and they do not all change together. When somebody renames a service and half the stack keeps working, this is why.
The five names
| Name | Set by | Scope | Resolvable by peers? |
|---|---|---|---|
| Container name | --name, or generated | whole daemon, must be unique | yes, on user-defined networks |
| Hostname | --hostname | inside the container only | no |
| Network alias | --network-alias, Compose aliases: | one network | yes |
| Compose service name | the key in services: | the projectβs networks | yes |
| Container ID | the daemon | whole daemon | yes, short form too |
The one that surprises people is --hostname. It sets what uname -n reports inside the container and what the shell prompt shows. It
does not create a DNS record. A container with
--hostname billing is not reachable as billing unless something
else also gave it that name.
$ docker inspect web --format '{{.Name}} {{.Config.Hostname}} {{range $n, $c := .NetworkSettings.Networks}}{{$n}}={{$c.Aliases}} {{end}}'/proj-web-1 8f2c1d4e5a6b proj_default=[web 8f2c1d4e5a6b]Illustrative output
Read that output carefully. The container name is proj-web-1. The
hostname is the short container ID. The alias on the project network
is web β the Compose service name. Peers connect to web, not to
proj-web-1, and certainly not to the hostname.
Aliases are network-scoped
A container attached to two networks can answer to different names on
each one. This is the mechanism behind βthe same database is db to
the application stack and postgres-primary to the backup stackβ.
docker network connect --alias postgres-primary backup-net db
docker inspect db --format '{{range $n, $c := .NetworkSettings.Networks}}{{$n}} -> {{$c.Aliases}}
{{end}}'In Compose the same thing is declarative:
services:
db:
image: postgres:16
networks:
app-net:
aliases: [db, primary]
backup-net:
aliases: [postgres-primary]
networks:
app-net:
backup-net:Disconnecting the container from backup-net removes
postgres-primary and leaves db intact. The names are attached to
the endpoint, not to the container.
Several containers, one alias
Nothing stops two containers sharing an alias, and Compose does exactly this when you scale a service:
$ docker compose up -d --scale web=3[+] Running 3/3
β Container proj-web-1 Started
β Container proj-web-2 Started
β Container proj-web-3 StartedIllustrative output
The embedded DNS now returns three addresses for web, and clients
distribute themselves across them according to how their resolver
orders the answer and how the client picks from the list.
What a rename actually changes
docker rename changes the container name. The daemon updates its
registry, so peers resolving the new name get an answer and the old
name stops resolving.
What it does not touch:
- The Compose service alias. A container created by Compose keeps
its
webalias afterdocker rename proj-web-1 web-old. The service name is an alias on the network, not the container name. - Established connections. A TCP connection resolved its peer once, at connect time. Renaming changes nothing for a socket that is already open.
- Anything that cached the address. This is the one that hurts.
The proxy that never re-resolves
nginx is the classic offender. Given this:
location / {
proxy_pass http://api:8080;
}
nginx resolves api once, when the configuration is loaded, and
compiles the result into the upstream. Recreate the api container β
a docker compose up -d after an image change is enough β and it
comes back with a different IP on the bridge network. nginx keeps
sending traffic to the address that no longer exists. The symptom is
a 502 that persists until somebody reloads nginx, and that reload
βfixesβ it in a way that teaches the wrong lesson.
The fix has two halves, and both are required:
resolver 127.0.0.11 valid=10s ipv6=off;
location / {
set $upstream_api http://api:8080;
proxy_pass $upstream_api;
}
resolver tells nginx which server to use for runtime lookups, and
valid=10s caps how long it caches. Putting the upstream in a
variable is what forces nginx to resolve at request time instead of
at load time. Without the variable, the resolver directive changes
nothing.
HAProxy has the same shape of problem and the same shape of fix β a
resolvers section plus resolve-prefer/resolve-opts on the
server line β and Traefik avoids it entirely by reading the Docker
API rather than DNS.
Sanity check
Knowledge check Β· 4 questions
Q1. You start a container with `--hostname billing` on a user-defined network. Can a peer container reach it as `billing`?
Q2. nginx proxies to `proxy_pass http://api:8080;`. The api container is recreated and gets a new IP. nginx keeps returning 502 until it is reloaded. Why?
Q3. A Compose-created container `proj-web-1` has the network alias `web`. You run `docker rename proj-web-1 web-old`. Which statements are true afterwards? Select all that apply.
Q4. On standalone Docker, the embedded DNS omits containers whose HEALTHCHECK is failing from the answer for a shared alias.
Passing score: 75%. Answers are checked in this browser.