Chapter 18Lesson 01~115 minutes

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.

Docker DNSService discoveryAliasesIPAMMulti-network

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.
Chapter 18 principle. A Docker name is useful only inside the network scope that can resolve it, and the resolved address is an endpoint allocation—not the service identity itself. Debug membership → resolver → name → endpoint → application connection in that order.

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.

Name-to-connection causality
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.

Dual-homed API
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.
Next lesson

Next: Guided Hands-On Workflow and Core Operations

Create two scoped bridge networks, attach front/API/back containers, prove aliases resolve only where intended, inspect endpoint addresses, and add an optional local IPv6 exercise without modifying daemon policy.

Knowledge check

A client can ping an old container IP but the service was recreated. What should the client use instead?

What does 127.0.0.11 in a custom-network container’s resolver configuration represent?

Can an alias declared on back be assumed resolvable from front?

Why can one container have two different IP addresses?

Does an IPv6 address inside a container prove external IPv6 connectivity?

Official references and version notes

Version baseline, verified 2026-09-21.

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.