Skip to main content
RunBook Academy

Docker & ContainersXXVI Β· DNS & Service DiscoveryService identity

Names, aliases, and what breaks when they change

Intermediate⏱ ~18 min

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

Not yet marked complete on this device.

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

NameSet byScopeResolvable by peers?
Container name--name, or generatedwhole daemon, must be uniqueyes, on user-defined networks
Hostname--hostnameinside the container onlyno
Network alias--network-alias, Compose aliases:one networkyes
Compose service namethe key in services:the project’s networksyes
Container IDthe daemonwhole daemonyes, 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.

Read-only / Safewhat a peer can resolve
$ 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”.

Configuration changedocker network connect
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:

Configuration changecompose.yaml
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:

Service impact possiblescale
$ docker compose up -d --scale web=3
[+] Running 3/3
βœ” Container proj-web-1  Started
βœ” Container proj-web-2  Started
βœ” Container proj-web-3  Started

Illustrative 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 web alias after docker 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

  1. Q1. You start a container with `--hostname billing` on a user-defined network. Can a peer container reach it as `billing`?

  2. 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?

  3. 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.

  4. 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.