How containers find each other without knowing IP addresses
Service discovery is the invisible backbone of every Docker Swarm cluster: internal DNS, virtual IP addresses and a cluster wide routing mesh make sure containers reach each other through stable names, even though the actual placement can change at any time. Understanding these mechanisms lets you resolve networking problems in Swarm much faster.
Table of contents
- 1. Why service discovery is needed at all
- 2. Internal DNS: service names as a stable address
- 3. VIP mode versus DNS round robin
- 4. Overlay networks as the technical foundation
- 5. Routing mesh: external reachability through any node
- 6. Network aliases and multiple networks per service
- 7. Diagnostics: finding service discovery problems
- 8. Limits of the built in service discovery
- 9. Service discovery compared: Swarm versus external solutions
- 10. Summary
- 11. FAQ
1. Why service discovery is needed at all
In a Docker Swarm cluster, container placement changes constantly. A node fails, a service gets scaled, a rolling update replaces old containers with new ones, and every time this happens the affected containers get a new internal IP address. Without service discovery, every application would need to maintain constantly updated IP lists, which would be error prone and hard to maintain in practice. This is exactly the problem that Docker Swarm's built in service discovery solves automatically and transparently for the application.
The core idea of service discovery in Swarm mode is simple: containers do not address each other via IP addresses, but via service names. A container that wants to reach the api service simply queries the hostname api, regardless of which node and IP address the actual instance currently runs on. This abstraction is the prerequisite for scaling, rolling updates and node failures staying invisible to the application itself.
2. Internal DNS: service names as a stable address
Every Docker Swarm cluster runs a built in DNS server that automatically creates an entry for every service inside each overlay network. As soon as a service named api exists in a network, every other container in that network can resolve the name api, without configuring an external DNS infrastructure like CoreDNS or Consul. This service discovery function is fully integrated into the Docker Engine and requires no additional component.
Technically, name resolution runs through an internal resolver that Docker automatically writes into every container's /etc/resolv.conf. When an application queries the hostname api, this resolver forwards the request to the overlay network's built in DNS server, which in turn returns the current list of IP addresses belonging to the service. This list gets updated immediately on every change, such as scaling or a container restart, so DNS responses never contain stale IP addresses.
# Create an overlay network for a stack
docker network create --driver overlay --attachable backend
# Deploy a service — Docker registers "api" as a DNS name automatically
docker service create --name api --network backend --replicas 3 \
registry.example.com/shop-api:1.4.0
# From another container on the same network, resolve the service name
docker exec -it $(docker ps -q -f name=worker) nslookup api
# Inspect which network aliases a service currently has
docker service inspect api --format '{{json .Endpoint.VirtualIPs}}'
3. VIP mode versus DNS round robin
Docker Swarm offers two different operating modes for service discovery, which differ in their load balancing behavior. The default mode is VIP mode, where every service receives a single, stable virtual IP address. Requests to this virtual address get distributed at the network level via IPVS, the Linux kernel module for layer 4 load balancing, across the actual container instances. This distribution is completely transparent to the requesting application and works even with a single DNS query.
Alternatively, a service can run in DNS round robin mode, where the DNS server returns a different IP address from the list of available containers for every request. This mode is rarely chosen explicitly, but becomes important when an application implements its own client side load balancing, or when IPVS is unavailable for certain kernel reasons. The key difference: VIP mode distributes at the network level, DNS round robin distributes at the name resolution level, with correspondingly different caching behavior in client libraries.
# Create a service explicitly using DNS round-robin instead of the VIP mode
docker service create --name api --network backend \
--endpoint-mode dnsrr --replicas 3 \
registry.example.com/shop-api:1.4.0
# Inspect the current endpoint mode of an existing service
docker service inspect api --format '{{.Spec.EndpointSpec.Mode}}'
# Switching an existing service back to VIP mode requires an update
docker service update --endpoint-mode vip api
4. Overlay networks as the technical foundation
Without overlay networks, there would be no cluster wide service discovery. An overlay network encapsulates container traffic in VXLAN tunnels that run over the physical node to node connections, creating a logical network that spans all nodes in the cluster, regardless of their actual physical network topology. Containers in the same overlay network reach each other directly through their service names, no matter which physical node they actually run on.
Every Swarm stack gets its own overlay network by default, connecting only the services belonging to that stack. This isolation is an important security aspect: a service in stack A cannot reach a service in stack B via service discovery by default, unless an explicitly shared network was defined. For scenarios where multiple stacks need to communicate, such as a central reverse proxy serving several independent application stacks, an additional, shared overlay network with attachable: true is created.
5. Routing mesh: external reachability through any node
The routing mesh complements internal service discovery with external reachability. When a service port gets published, for example with --publish 8080:8080, Docker opens this port on every single node in the cluster, regardless of whether an instance of the service actually runs on that node. An incoming request to any node gets internally forwarded through the routing mesh to a node where a healthy container actually runs.
This property considerably simplifies external load balancer configurations, because every node in the cluster serves as a valid target for incoming traffic. An external load balancer only needs to know all node IP addresses, the internal distribution to healthy containers is handled by the Swarm routing mesh itself. For use cases where the client's source IP address matters, such as IP based access control, the host mode must be used instead of the default ingress mode, since the routing mesh otherwise alters the source address through NAT.
6. Network aliases and multiple networks per service
Besides the automatically registered service name, service discovery in Swarm mode supports additional network aliases, through which the same service can be made reachable under multiple names. This is practical when a migration happens gradually and an old service name needs to keep working alongside the new name, or when several logical roles should point to the same physical service.
A service can also be attached to multiple overlay networks at the same time. This becomes relevant when a service needs to communicate both with an internal backend network and a shared proxy network, without backend services becoming directly visible to the proxy. Every additional network adds another DNS zone to service discovery in which the service name can be resolved, which makes network segmentation considerably more flexible than a single, flat network for the entire cluster.
# Attach a service to an additional network with a custom alias
docker service update \
--network-add name=proxy-net,alias=shop-api-legacy \
api
# List all networks a service is currently attached to
docker service inspect api --format '{{json .Spec.TaskTemplate.Networks}}'
7. Diagnostics: finding service discovery problems
When a container cannot reach another service through service discovery, the first question is always whether both containers are attached to the same overlay network. A common mistake is a service accidentally running in a different stack's network, without a shared network existing between them. docker network inspect shows all containers currently attached and their assigned IP addresses in that network.
Another common mistake involves capitalization or mismatched service names between the compose file and the actual call in code. Since Docker DNS names are generally case insensitive but otherwise matched exactly, a typo in a service name results in a classic Name or service not known error. Running docker exec -it lets you check directly from a running container whether name resolution actually works, before digging deeper into the application itself for the error.
# Step-by-step diagnostic sequence for service discovery failures
# 1. Confirm both containers share the same overlay network
docker network inspect backend --format '{{range .Containers}}{{.Name}} {{end}}'
# 2. Confirm the target service actually has running, healthy tasks
docker service ps api --filter "desired-state=running"
# 3. Resolve the service name from inside the calling container
docker exec -it $(docker ps -q -f name=worker) getent hosts api
# 4. Check whether the service uses VIP or DNS round-robin mode
docker service inspect api --format '{{.Spec.EndpointSpec.Mode}}'
# 5. If DNS resolves but connections still fail, check firewall
# rules on the host and confirm the overlay network's VXLAN
# traffic (UDP 4789) is not blocked between nodes
8. Limits of the built in service discovery
Docker Swarm's built in service discovery covers most standard cases, but has limits that become relevant for more complex requirements. It offers no native circuit breaking, no advanced routing rules based on HTTP headers, and no automatic retry logic on failed connections, features a service mesh like Linkerd or Istio would additionally provide. For most applications with a manageable number of services, this extra functionality is not necessary, though.
Another limit concerns multi cluster scenarios: service discovery in Swarm mode works exclusively within a single cluster. If services need to communicate across multiple independent Swarm clusters, for example between different data centers, an external solution like a global DNS service or a dedicated service mesh with multi cluster support is required. For the vast majority of production setups with a single cluster, though, the built in solution is entirely sufficient.
A third, often overlooked limit concerns convergence speed during very rapid changes. If a service gets scaled or restarted multiple times in quick succession, there can be a brief moment where DNS responses still contain stale entries until cluster state has fully propagated. For the vast majority of applications, this millisecond level delay is irrelevant, but for very latency sensitive systems it is worth looking at the retry behavior of your own client libraries.
9. Service discovery compared: Swarm versus external solutions
The following table compares Swarm's built in service discovery with external alternatives used in larger or more heterogeneous environments.
| Aspect | Docker Swarm service discovery | External service mesh |
|---|---|---|
| Setup | Built in, no additional install | Additional component, more configuration |
| Name resolution | Internal DNS, automatic | Usually also DNS, plus sidecar proxies |
| Circuit breaking | Not available | Natively supported |
| Multi cluster | Not supported | Partially supported, depending on product |
| Overhead | Minimal, no sidecar | Sidecar proxy per container common |
For the vast majority of Docker Swarm clusters with a manageable number of services, the built in service discovery is entirely sufficient and considerably simpler to operate than an additional service mesh with its own sidecar overhead.
Mironsoft
Docker Swarm networking and cluster diagnostics
Networking problems in your Docker Swarm cluster?
We analyze overlay networks, service discovery and routing mesh configurations in your cluster and fix the root cause instead of just the symptoms.
Network audit
Full review of overlay networks, aliases and segmentation
Troubleshooting
Live diagnostics of DNS resolution, routing mesh and endpoint modes
Architecture consulting
Assess whether a service mesh is actually needed before adopting one
10. Summary
Service discovery in Docker Swarm mode rests on three interacting mechanisms: internal DNS for name resolution, VIP mode for transparent load distribution, and the routing mesh for external reachability through any node. Containers reach each other through stable service names, regardless of their actual, constantly changing placement in the cluster. This abstraction is the foundation that keeps scaling, rolling updates and node failures transparent to the application itself.
For the vast majority of production setups, the built in service discovery is entirely sufficient, without needing an additional service mesh with its own sidecar overhead. Anyone who understands the basics of DNS resolution, overlay networks and the routing mesh can independently diagnose the most common networking problems in a Swarm cluster, instead of falling into confusion at every connection error.
Service discovery in Docker Swarm mode: the essentials at a glance
Internal DNS
Every service automatically gets a DNS name inside the overlay network, no extra configuration.
VIP mode
By default, IPVS transparently distributes requests across healthy container instances.
Routing mesh
Published ports are reachable on every node, regardless of the actual container placement.
Diagnostics
docker network inspect and getent hosts inside a container are the first stops for troubleshooting.