Docker DNS, Service Discovery, Aliases, IPv4/IPv6, Custom Subnets, and Multi-Network Applications: Concepts, Architecture, and Mental Model
Design Docker name resolution and multi-network connectivity around explicit membership, embedded DNS, network-scoped aliases, IPAM, and stable service identity.
Learning objectives
- Explain how Docker resolver configuration, embedded DNS, network-scoped names/aliases, endpoint addresses, and application connections fit together.
- Distinguish stable service identity from dynamically allocated container IP addresses and from host/external DNS.
- Inspect network membership, aliases, resolver state, IPv4/IPv6 allocations, subnet/gateway state, and per-network endpoints without changing them.
- Explain why one container attached to multiple networks has multiple endpoint identities and why an alias is meaningful only on its declaring network.
- Recognize platform-sensitive IPv6 assumptions and keep dual-stack testing separate from the mandatory IPv4 learning path.
1. Why stable names matter more than container IPs
Chapter 17 established that a container can have one endpoint per
attached Docker network. Chapter 18 adds the naming layer. If a
client hard-codes 172.x.x.x, it couples itself to one
allocation that can change after recreation. If it connects to a
service name or a deliberate network-scoped alias, Docker can
resolve the current endpoint address for that network.
This does not make networking magical. Name resolution can succeed while the application is down, listening on the wrong port, or bound only to loopback. Conversely, a healthy application can be unreachable because the caller is not attached to the network where the name exists. DNS evidence and connection evidence answer different questions.
2. Mental model: resolver → scoped name → endpoint → socket
On a user-defined Docker network, a Linux container normally points resolver queries at Docker's embedded DNS service. Docker resolves container/service names and aliases that are valid on that network, then forwards unrelated external queries toward the host-configured DNS path. The answer maps the logical name to an endpoint address on the shared network. The application then opens its TCP/UDP connection to that address and port.
flowchart TD
A[Application asks for api] --> R["/etc/resolv.conf resolver configuration"]
R --> D[Docker embedded DNS custom network]
D --> S[Service/container name or network-scoped alias]
S --> E[Endpoint address on caller's shared network]
E --> C[Application connect IP + port]
D --> X[External DNS forwarding for non-Docker names]
Docker documents 127.0.0.11 as the embedded DNS server
address for containers on custom networks. That address is an
internal resolver service, not the address of another application
container. The default legacy bridge behaves differently: it does
not provide the same automatic name-based discovery contract.
3. The identities you must not collapse
| Identity | Example | Scope | What it proves |
|---|---|---|---|
| Service/container name | api |
Docker/Compose network membership | Human-readable discovery key; not an IP guarantee. |
| Network alias | api-internal |
One specific network | Alternative discovery name valid only where declared. |
| Endpoint IP | 172.30.18.4 |
One endpoint on one network | Current allocation; can change after recreation. |
| Container ID | sha256… / short ID |
Docker daemon | Exact container object; not a DNS contract. |
| Host DNS name | db.example.test |
External resolver/organization | Lives outside Docker embedded discovery unless explicitly integrated. |
| Published host address | host IP + port | Host exposure path | Separate from container-to-container discovery; Chapter 19 topic. |
4. Aliases and service discovery are network-scoped
A multi-homed service can have different aliases on different
networks. For example, an API may be named api on a
front-end network and api-internal on a back-end
network. A front-end container that is not a member of the back-end
network should not rely on api-internal, and a
database-only alias should not become a global hostname.
Compose makes the same principle explicit: services attached to a project network can discover one another by service name, and aliases are declared under the particular network attachment. If multiple containers share one alias, Docker does not guarantee which one an individual lookup selects. Treat shared aliases as a deliberate load-discovery design, not accidental naming.
5. What /etc/resolv.conf proves—and what it does not
Resolver configuration tells you where the container sends DNS
queries and which search/options are present. On a custom Docker
network, seeing nameserver 127.0.0.11 is evidence that
Docker's embedded resolver is in the path. It does
not prove that a particular name exists, that a
network alias is declared, or that the target process is reachable.
# Read-only evidence from an existing container:
docker inspect <container> --format '{{json .NetworkSettings.Networks}}'
docker exec <container> cat /etc/resolv.conf
docker exec <container> nslookup <peer-name>
# Resolve first; then test the application separately.
docker exec <container> wget -qO- http://<peer-name>:8080/
6. A multi-network container has one endpoint per network
Attaching one container to front and
back does not give it one universal Docker IP. Each
attachment has its own endpoint, address, gateway, and aliases.
docker inspect exposes these under
NetworkSettings.Networks. This matters for routing and
for the source/destination address seen by peers.
flowchart TD
F[frontend front network] --> AF[api endpoint front address + alias api]
AF --> API[API process]
API --> AB[api endpoint back address + alias api-internal]
AB --> B[database back network]
O[outsider front only] -. no back membership .-> B
7. Custom subnets are allocation policy, not service identity
Docker IPAM can allocate from explicitly configured IPv4 or IPv6 subnets. Custom subnets are useful for conflict avoidance, routing integration, and controlled static-address cases, but they also create an ownership obligation: the chosen ranges must not overlap other Docker networks, VPNs, VPCs, host routes, or adjacent infrastructure.
Use dynamic addresses by default and record the network name/ID plus
subnet. Static ipv4_address/ipv6_address
is justified only when an external protocol or integration truly
requires a stable address; Compose requires an IPAM subnet that
covers each static address.
8. IPv6 is a capability-gated extension
Current Docker Engine documentation states that IPv6 networking is
supported on Docker daemons running on Linux hosts. A user-defined
network can be created with IPv6 enabled and, if no IPv6 subnet is
supplied and the daemon has no IPv6 default pool, Docker can
allocate a ULA range. Compose exposes the same capability through
enable_ipv6: true and IPAM configuration.
Do not infer Internet IPv6 reachability from “the container has an IPv6 address.” Local endpoint allocation, host forwarding, upstream routing, DNS AAAA records, and application binding are separate states. The labs keep IPv6 local and optional unless host routing is intentionally configured.
9. Read-only baseline before creating anything
docker version
docker info
docker context show
docker compose version || true
docker network ls
docker ps -a --no-trunc
# Record the lab image identity before use.
docker pull busybox:1.36.1
docker image inspect busybox:1.36.1 \
--format 'ID={{.Id}} RepoDigests={{json .RepoDigests}}'
# Inspect existing Docker network IPAM and endpoint membership.
docker network inspect bridge
# For any existing custom network:
docker network inspect <network> \
--format 'Driver={{.Driver}} Internal={{.Internal}} IPAM={{json .IPAM.Config}} Containers={{json .Containers}}'
# For any existing container:
docker inspect <container> \
--format 'Networks={{json .NetworkSettings.Networks}}'
Record the active Docker context. Running the same commands against the wrong context can make a correct network appear “missing.” On Docker Desktop, remember that Linux networking is implemented inside the managed VM boundary; prefer Docker API/container-visible evidence over assumptions about host-side Linux bridge devices.
10. Reproducibility means preserving network intent and evidence
| Evidence | Why retain it |
|---|---|
| Engine/CLI/Compose version + context | Determines feature/platform behavior and which daemon owns the networks. |
| Network name + ID + driver + subnet/gateway | Identifies the exact allocation domain. |
| Container ID + network memberships + aliases | Shows who is actually allowed to discover whom. |
/etc/resolv.conf + lookup result |
Separates resolver path from name existence. |
| Endpoint IPv4/IPv6 addresses | Documents current allocation without treating it as durable identity. |
| Application connection result/log | Proves the service layer after DNS succeeds. |
| Host/external DNS assumption | Marks the boundary where Docker discovery stops. |
Knowledge check
A client can ping an old container IP but the service was recreated. What should the client use instead?
Use the service/container name or a deliberate network-scoped alias on a shared user-defined network. The IP is an allocation, not the durable identity.
What does 127.0.0.11 in a custom-network
container’s resolver configuration represent?
Docker’s embedded DNS service inside the container network namespace. It resolves Docker-scoped names and forwards external queries; it is not an application container address.
Can an alias declared on back be assumed
resolvable from front?
No. Aliases are network-scoped. The caller must share the network where that alias is declared.
Why can one container have two different IP addresses?
A container attached to two networks has two endpoints, each with its own address and network-specific aliases/routes.
Does an IPv6 address inside a container prove external IPv6 connectivity?
No. Endpoint allocation is only one layer; host forwarding, upstream routing, external DNS, and application binding must be verified separately.
Official references and version notes
-
Docker Docs — Networking overview
— resolver behavior, custom-network embedded DNS, and
127.0.0.11. - Docker Docs — Bridge network driver — user-defined bridge isolation and automatic name/alias resolution.
- Docker Docs — docker network connect — endpoint attachment and network-scoped aliases.
- Docker Docs — Networking in Compose — project networks and service-name discovery.
- Compose Specification — service network aliases — aliases are scoped to the network on which they are declared.
-
Compose Specification — networks
— IPAM,
enable_ipv4,enable_ipv6, internal/external networks, and custom names. - Docker Docs — IPv6 networking — Linux-daemon support, IPv6 network creation, ULA allocation, and Compose examples.
- Docker Engine 29 release notes — current Engine behavior and networking fixes.
Docker Engine 29.8.1 (released 2026-09-15) is the current Engine 29 release in the primary release notes, and Docker Compose v5.5.1 is the current upstream Compose release. The runnable labs deliberately record your Engine/CLI/Compose versions and context because DNS, IPv6, Desktop networking, firewall integration, and helper-tool availability vary by platform. The mandatory path uses only local disposable networks and containers; IPv6 is an optional capability-gated extension.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.