skip to content

You attach three Docker containers to the same network, each with `--network-alias api`. What does a lookup of the name `api` return, and what are the limits of relying on that for load balancing?

level: middleimportance: should knowfreq 36%

answer

  1. alias need not be unique
  2. multi-answer record set, shuffled per query
  3. no health checks, no draining
  4. JVM/pool caching pins traffic
  5. proxy in front for real balancing

basics

~20 s

The lookup returns all three container IPs, with the order shuffled per query, so clients spread naturally. It is DNS round-robin only: no health checking, no connection-level balancing, and client-side caching or long-lived connections can pin traffic to one container.

solid answer

~60 s

A network alias is an extra DNS name registered for a container on a specific network, and **several containers may share one alias**. The embedded resolver then returns a multi-answer record set containing every matching container's IP, reordered between queries so different clients pick different targets. That is genuine service discovery but weak load balancing: - **No health awareness.** A container that is up but broken stays in the record set until it stops or leaves the network. - **Client behaviour decides everything.** Most clients use the first address returned; runtimes that cache aggressively (a JVM with a long `networkaddress.cache.ttl`, some HTTP clients) resolve once and stay pinned. - **Connection reuse defeats it.** With HTTP keep-alive or a connection pool you resolve once and then reuse that socket indefinitely. - **No weighting, no draining, no retries.** So aliases are excellent for *addressing* a role (`db`, `cache`) and for blue/green style cutovers, but if you need real balancing you put a proxy behind the alias, or move to an orchestrator whose service layer distributes per connection.

code

bash · 9 lines
bash
docker network create app
for i in 1 2 3; do
  docker run -d --name api-$i --network app --network-alias api nginx:alpine
done

docker run --rm --network app nicolaka/netshoot dig +short api
# 172.18.0.4
# 172.18.0.2
# 172.18.0.3   (order varies per query)

go deeper

for a junior

Know that several containers can share an alias and a lookup returns all their IPs in varying order.

for a middle

Explain that this is DNS round-robin, and name the two things that break it: client-side caching and connection reuse.

for a senior

Discuss the absence of health checks and draining, and when you would put a proxy in front of the alias instead.

for a principal

Position DNS discovery as a naming contract, not a traffic-management layer, and set the threshold at which you adopt a proxy or an orchestrator's service abstraction.

## What an alias is Every container on a user-defined network is registered under its container name. `--network-alias <name>` adds **additional** names for that container on that network; in Compose the equivalent is `networks.<net>.aliases`, and the service name itself is registered as an alias. Aliases are per network: attach a container to two networks and you can give it a different alias on each - useful when the same service is `payments` internally and `api` to the frontend tier. Unlike a container name, an alias is **not required to be unique**. Registering the same alias on several containers is explicitly supported and is Docker's built-in form of service discovery. ## What the lookup returns With three containers sharing the alias `api`, a query for `api` returns three address records. The embedded resolver **shuffles the order** between queries, so a population of clients that each take the first answer spreads across the three. This is classic **DNS round-robin**. What it is not: - It is not a load balancer sitting in the data path. Once the client picks an IP, all its traffic goes straight to that container. - It carries no health signal. Docker removes a record when the container stops or is disconnected from the network - not when the application inside starts returning errors. - It has no notion of load, weight, session affinity or draining. ## Why real traffic often does not spread **Caching.** The record TTL is short, but plenty of clients ignore it. The canonical example is the JVM, which caches successful lookups according to `networkaddress.cache.ttl` and historically cached them forever in some configurations; the fix is to set that TTL to a small value. Language runtimes and libc-level caching daemons behave differently, so "it balanced in my test with `curl` but not in the app" is a normal outcome - `curl` re-resolves per invocation, an application does not. **Connection pooling and keep-alive.** An HTTP client with a pool resolves once, opens sockets, and reuses them for hours. gRPC over HTTP/2 is worse: one long-lived connection carries every request, so one DNS answer decides your entire traffic distribution. **Small client counts.** Round-robin only averages out over many independent resolvers. Two clients and three backends will look unbalanced no matter what. ## Where aliases genuinely shine - **Stable role names.** Point configuration at `db` or `cache` and swap the container behind it without touching configuration. - **Cutovers.** Start the new version with the same alias, verify, then stop the old container; new lookups drift to the replacement. - **Multiple identities.** One container can answer to both `api` and `legacy-api` during a rename. - **Per-network naming.** Different aliases on the frontend and backend networks keep tier-appropriate names. ## The upgrade path If you need actual balancing on a single host, put a reverse proxy (nginx, HAProxy, Traefik) on the network and let *it* resolve the alias, ideally with active health checks and periodic re-resolution. Across hosts, that is precisely the job an orchestrator's service abstraction takes over - it keeps a stable name but distributes per connection and removes unhealthy endpoints from rotation. Presenting DNS round-robin as equivalent to a load balancer is the mistake interviewers listen for.

  • A team scales a Compose service to five replicas but almost all requests hit one replica. Why?
    The client resolved the name once and kept using that address - either DNS caching in the runtime or, more often, a connection pool or HTTP keep-alive that reuses established sockets. DNS round-robin only distributes at resolution time, so long-lived connections pin traffic. The fix is a proxy that balances per connection or per request, or forcing periodic re-resolution.
  • How does Docker remove a dead backend from the alias record set?
    Only by container lifecycle: when the container stops, is removed, or is disconnected from the network, its record disappears. There is no application health check, so a container whose process is hung or returning errors keeps receiving traffic. Health-aware removal requires a proxy or an orchestrator's endpoint controller.

saying these in an interview costs you the question

  • Calling DNS round-robin a load balancer with health checking
  • Assuming every client honours the DNS TTL and re-resolves
  • Expecting balancing to work over a single long-lived HTTP/2 or gRPC connection
  • Believing an alias must be unique per network
  • Testing with curl, seeing spread, and concluding the application will behave the same

context