Docker Networking: Bridge, Host, DNS and Service Discovery Explained
AI generated
Docker · Networking · DNS · Service Discovery
Understanding Docker networking
Bridge, host, DNS and service discovery

Containers do not talk to each other automatically. Docker networks define who can reach whom, and who cannot. Bridge networks, embedded DNS, service discovery in Compose, and secure network segmentation are the building blocks of any resilient container infrastructure.

13 min read Bridge · Host · none · Overlay · DNS · Service Discovery Docker Engine · Docker Compose · Docker Swarm

1. Why Docker networking matters more than ports

The first instinct when connecting containers is to open a port: ports: "3306:3306" and the database container becomes reachable. The problem is that the database is then also reachable from every other process on the host, not just from the application container. Docker networking solves this more elegantly: containers on the same user-defined network can reach each other directly by service name, without any port forwarding to the host. Ports only need to be opened when a service must be reachable from the outside.

Once you understand Docker networking properly, you build stacks where the database is reachable only from the application container, the Redis cache is only visible to the PHP application, and the reverse proxy is the single service that exposes a host port. That is not just more secure, it is also clearer: the network topology in the Compose file documents which service is allowed to talk to which.

2. Bridge networks: the default network driver

The default network driver in Docker networking is bridge. A bridge network creates a virtual network bridge on the host to which containers are attached. All containers on the same bridge network can reach each other via their IP addresses. On user-defined bridge networks, unlike the default bridge network, name resolution also works through the embedded DNS server, so containers can address each other by service name instead of by IP.

The default bridge network that Docker creates at startup has one important difference from user-defined bridge networks: it does not support embedded DNS. Containers on the default bridge network can only connect via IP or through the deprecated --link mechanism. That is why the Docker documentation explicitly recommends always creating your own Docker networks with the bridge driver instead of using the default network. Docker Compose does this automatically.


# compose.yaml: explicit network definitions for clean topology
networks:
  frontend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24
  backend:
    driver: bridge
    internal: true   # No external access, purely internal communication
  db:
    driver: bridge
    internal: true

services:
  nginx:
    image: nginx:1.27-alpine
    networks:
      - frontend      # Exposed to host via ports
      - backend       # Can reach phpfpm
    ports:
      - "80:80"
      - "443:443"

  phpfpm:
    image: php:8.4-fpm-alpine
    networks:
      - backend       # Reachable from nginx
      - db            # Can reach mysql and redis
    # No ports needed, only nginx talks to phpfpm

  mysql:
    image: mysql:8.4
    networks:
      - db            # Only phpfpm can reach mysql
    # No host port, not accessible from outside the db network

3. Embedded DNS: how containers find each other by name

On user-defined Docker networks, Docker runs an embedded DNS server at the IP address 127.0.0.11. Every container on a user-defined network automatically has this DNS server configured as its nameserver. When PHP-FPM wants to address a database container named mysql by hostname, it queries this DNS server, which resolves the current container name. This works for service names from Compose files, network aliases, and container names.

The embedded DNS is dynamic: when a container restarts and gets a new IP address, DNS resolution updates immediately. That is why service names in database connection strings are more stable than IP addresses in Docker networking. IPs can change on container restarts, but the service name stays constant. For Magento this means mysql as the database host in env.php, redis as the cache backend, and opensearch as the search host, with no fixed IP addresses.

4. Service discovery in Docker Compose

Docker Compose implements service discovery automatically: every service name in the Compose file is registered as a DNS hostname on the network. When a service has multiple replicas, the DNS server returns all of their IP addresses, giving round-robin DNS as a simple form of load balancing. This is the mechanism that lets services in a Compose stack find each other by name without setting environment variables full of IP addresses.

For more advanced service discovery scenarios in Docker Compose, network aliases offer a solution: a container can be assigned multiple names on a network. A migration container can be reachable under the alias db-migrate, while the regular database container is addressed as mysql. When two Compose stacks need to communicate, external networks can be referenced: one stack creates the network, the other attaches to it as external.


# Service discovery with aliases and cross-stack networking
services:
  mysql:
    image: mysql:8.4
    networks:
      db:
        aliases:
          - database     # Reachable as both "mysql" and "database"
          - db-primary   # Useful for read/write splitting

  redis:
    image: redis:7.4-alpine
    networks:
      backend:
        aliases:
          - cache        # phpfpm can use "cache" as hostname
          - session-store

  phpfpm:
    networks:
      - backend
      - db

# Cross-stack networking: reference a network from another Compose project
networks:
  shared-proxy:
    external: true       # Created by the reverse-proxy stack
    name: proxy_default  # Exact network name from the other stack
  backend:
    driver: bridge
    internal: true
  db:
    driver: bridge
    internal: true

# Check DNS resolution inside a container
# docker exec phpfpm nslookup mysql
# docker exec phpfpm getent hosts redis

5. Host mode and none: when to skip the bridge driver

Besides bridge, Docker networking knows two other important modes: host and none. In host mode, the container shares the host's network namespace directly. There is no network isolation, no port translation, and no embedded DNS. The container binds directly to the host's network interfaces. This eliminates the overhead of the Docker network bridge and matters for performance-critical network applications or tools that need to observe the host network stack directly.

The none mode disables networking entirely. The container only has a loopback interface and cannot establish or accept any network connections. This is the most restrictive isolation level in Docker networking and makes sense for batch-processing containers that perform file transformations and need no network access at all. In security audits and compliance scenarios, none rules out an entire class of attack vectors.

6. Network segmentation: isolating frontend, backend and database

The most important security measure in Docker networking is segmentation into multiple networks. A typical three-tier model separates frontend, backend, and data layer. The reverse proxy (nginx, Traefik) sits on the frontend network and has a port on the host. The application server (PHP-FPM) is reachable on the frontend network for the reverse proxy and on the backend network for database services. MySQL, Redis, and OpenSearch live exclusively on the internal network and are not reachable from the frontend network.

The internal: true flag on a Docker network prevents containers on that network from establishing outbound connections to the internet. This ensures that a compromised database instance cannot exfiltrate data. For development environments this matters less, but for production and staging environments it is an important layer in a defense-in-depth strategy. The network definition in Compose thus doubles as explicit documentation of the allowed communication paths.


# Verify network topology: which networks is a container connected to?
docker inspect phpfpm --format '{{ json .NetworkSettings.Networks }}' | jq .

# List all networks and their containers
docker network ls
docker network inspect backend --format '{{ range .Containers }}{{ .Name }} {{ end }}'

# Test DNS resolution and connectivity between containers
docker exec phpfpm nslookup mysql
docker exec phpfpm curl -s http://nginx/health || true

# Check if internal network truly blocks outbound traffic
docker exec mysql curl -s --max-time 3 https://example.com || echo "Blocked, internal:true works"

# Diagnose network issues: inspect routing and iptables rules
docker exec phpfpm ip route
docker exec phpfpm cat /etc/resolv.conf   # Should show 127.0.0.11 as nameserver

7. Network aliases and multiple networks per container

A container can participate in several Docker networks at once, each with its own IP address and its own aliases. This enables differentiated communication rules: an API gateway container is reachable as api-gateway on the public network, under the alias gateway-internal on the backend network, and as metrics-endpoint on the monitoring network. Each network has its own DNS resolution, so a service can appear under different names depending on which network is looking.

Network aliases are especially useful for blue-green deployments and service migrations: the new container gets the same alias as the old one, so existing connections are served by the new service without needing to change the connection configuration of dependent services. In Docker networking with multiple containers sharing the same alias, the embedded DNS automatically implements DNS round-robin, a simple form of load balancing with no extra infrastructure.

8. Overlay networks for multi-host setups

When containers on different physical or virtual hosts need to communicate, bridge Docker networks hit their limits: they only work on a single host. Overlay networks extend the concept across multiple hosts by using VXLAN (Virtual Extensible LAN) to tunnel container network packets over the physical network. For Docker Swarm and Docker-native multi-host setups, the overlay driver is the standard.

For smaller teams using Docker networking without Swarm, overlay is less relevant since Kubernetes or Docker Swarm bring their own network layers. What is important to understand, though, is the underlying principle: overlay networks enable the same service discovery mechanism as bridge networks, just across host boundaries. A container on host A can address a container on host B by service name, as long as both are on the same overlay network. This is the foundation that lets horizontally scaled services in Swarm clusters appear as a single unit.

9. Network drivers compared side by side

Choosing the right network driver depends on isolation requirements, performance needs, and deployment topology. The table below summarizes the most important Docker network drivers.

Driver DNS / service discovery Isolation Typical use case
bridge (user-defined) Yes, by service name High Default for Compose stacks
bridge (default docker0) No DNS Medium Avoid, legacy
host Host DNS None Performance-critical services
none No network Maximum Batch jobs with no network access
overlay Yes, multi-host High Docker Swarm, multi-host

For most Docker networking setups with Docker Compose, user-defined bridge networks are the right choice. They offer DNS-based service discovery, clear isolation, and straightforward configuration. Host mode and none are special cases that should only be used when there is a concrete reason to do so. Overlay networks only come into play once the stack is spread across multiple hosts.

Mironsoft

Docker network architecture, container infrastructure and DevOps consulting

Want Docker networking that is secure and scalable?

We design the network topology for your container stack, with clear segmentation, service discovery without port chaos, and a documented communication architecture.

Network audit

Analyze your existing Docker network topology and identify security gaps

Segmentation

Separate frontend, backend and database layer into isolated internal networks

Multi-stack setup

Cross-stack communication via external networks and reverse-proxy integration

10. Summary

Docker networking is the invisible layer that decides which container can talk to which. User-defined bridge networks with the embedded DNS server at 127.0.0.11 enable service discovery by name, with no port forwarding and no fixed IP addresses. The three-tier model of frontend, backend, and database networks, with internal: true on the inner layers, creates a clear, documented security architecture.

Network aliases and multiple networks per container enable flexible communication rules where a service is reachable under different names depending on which network is looking. For multi-host setups, overlay networks solve the problem of host boundaries. The most important principle in Docker networking is: as little connectivity as possible, as much as necessary, and always user-defined bridge networks instead of the legacy default network.

Docker networking, the essentials at a glance

Embedded DNS

Docker runs DNS at 127.0.0.11 on user-defined networks. Service names from Compose are registered automatically, no fixed IPs needed.

Network segmentation

Separate frontend, backend and database into distinct networks. internal: true blocks outbound connections for internal networks.

Port discipline

Only open ports for services that must be reachable from the host. Internal services like MySQL and Redis need no host ports.

Aliases & multi-network

Network aliases allow multiple names per service. Containers can belong to several networks at once, each with its own IP and DNS view.

11. FAQ: Docker networking

1Bridge vs. host networking in Docker?
Bridge creates an isolated virtual bridge. Host disables isolation entirely: the container uses the host network stack directly, with no port translation.
2Why avoid the default docker0 network?
No embedded DNS. Containers are only reachable by IP or the deprecated --link mechanism. User-defined bridge networks provide DNS and better isolation.
3Find out which networks a container is on?
docker inspect <container> --format '{{ json .NetworkSettings.Networks }}' lists all networks with IPs. docker network inspect <net> shows all connected containers.
4Open a MySQL port on the host?
Not necessary when the app and DB are on the same network. PHP-FPM reaches MySQL by service name. Only open a host port for local DB tools like TablePlus.
5What does internal: true do?
Prevents outbound internet connections from this network. Inbound Docker-internal connections remain possible. Recommended for DB and cache networks.
6Connect two Compose stacks?
Stack A creates the network. Stack B references it with external: true and the exact network name. Then they are reachable by service name.
7What are network aliases for?
Additional DNS names per network. Useful for blue-green deployments or when a service should appear under different names on different networks.
8Which DNS server does a container use?
Docker automatically configures 127.0.0.11 in /etc/resolv.conf. This internal DNS resolves service names and forwards external queries to the host DNS.
9When do I need overlay networks?
When containers on different physical hosts need to communicate, typical for Docker Swarm. For single-host setups, bridge networks are fully sufficient.
10Debug connection problems between containers?
nslookup <service> inside the container checks DNS. curl http://<service>:<port> tests connectivity. cat /etc/resolv.conf shows the DNS server. network inspect shows connected containers.