Docker Networking
Understand Docker bridge, host, and none networks, user-defined networks, DNS-based service discovery, and port publishing with examples.
Containers rarely run alone: a web app talks to a database, a cache, and other services. Docker provides virtual networks that let containers find and reach each other while staying isolated from the outside world unless you explicitly publish ports. Knowing the network drivers and how name resolution works solves most "container cannot connect" problems.
Network Drivers
| Driver | Behaviour | Typical use |
|---|---|---|
bridge |
Private virtual network on a single host; containers get their own IP | Default for standalone containers; user-defined bridges for multi-container apps |
host |
Container shares the host's network stack; no isolation, no port mapping | Maximum network performance, or when many ports are needed |
none |
Only a loopback interface | Fully isolated containers |
overlay |
Multi-host network (used with Swarm) | Services spanning several Docker hosts |
macvlan |
Container gets its own MAC address on the physical network | Legacy apps that expect to be directly on the LAN |
docker network ls
# NETWORK ID NAME DRIVER SCOPE
# 1a2b3c4d5e6f bridge bridge local
# 7a8b9c0d1e2f host host local
# 3f4e5d6c7b8a none null local
Default Bridge vs User-Defined Bridge
Containers started without --network join the default bridge network. On it, containers can reach each other by IP address only. A user-defined bridge network adds automatic DNS resolution by container name, better isolation, and the ability to attach and detach containers at runtime.
| Feature | Default bridge |
User-defined bridge |
|---|---|---|
| Resolve containers by name | No (IP only) | Yes |
| Isolation from unrelated containers | Weaker, all share one network | Better, only attached containers |
| Attach/detach running containers | Requires restart | docker network connect/disconnect |
Container-to-Container Communication
docker network create appnet
docker run -d --name db --network appnet \
-e POSTGRES_PASSWORD=secret postgres:16
docker run --rm --network appnet postgres:16 \
pg_isready -h db -U postgres
# db:5432 - accepting connections
The second container reaches the first simply by using the hostname db. Docker's embedded DNS server (at 127.0.0.11 inside the container) resolves container names and network aliases on user-defined networks.
Inside a shared network you use the container's port directly (db:5432). You do not need to publish the port to the host for container-to-container traffic.
Publishing Ports
Publishing makes a container port reachable from outside the Docker network.
docker run -d --name web -p 8080:80 nginx:1.27 # host 8080 -> container 80 (all interfaces)
docker run -d --name web2 -p 127.0.0.1:8081:80 nginx:1.27 # only reachable from the host itself
docker run -d --name web3 -p 80 nginx:1.27 # random host port
docker run -d --name web4 -P nginx:1.27 # publish all EXPOSEd ports to random ports
docker port web
# 80/tcp -> 0.0.0.0:8080
EXPOSE in a Dockerfile only documents a port; -p is what publishes it.
Host and None Networks
# Host: nginx listens directly on the host's port 80 (-p is ignored)
docker run -d --network host nginx:1.27
# None: no external connectivity
docker run --rm --network none alpine ip addr
# only the "lo" interface is shown
Host networking works on Linux hosts. On Docker Desktop the container shares the network of the Docker VM, not your laptop's, unless host networking is specifically enabled in settings.
Networking in Docker Compose
Compose creates a default network for the project and attaches every service to it. Services reach each other by service name.
services:
api:
image: my-api:1.0
environment:
DB_HOST: db
networks: [backend, frontend]
ports:
- "8080:8080"
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret
networks: [backend]
networks:
frontend:
backend:
Here db is only on backend, so containers on frontend cannot reach it.
Inspecting and Debugging Networks
docker network inspect appnet # subnet, connected containers, IPs
docker inspect -f '{{json .NetworkSettings.Networks}}' db
docker exec -it api sh -c "getent hosts db" # DNS resolution test
docker network connect appnet existing-container
docker network disconnect appnet existing-container
Common Mistakes
- Using
localhostto reach another container.localhostinside a container is the container itself. Use the service or container name. - Relying on container names on the default bridge. Name resolution only works on user-defined networks.
- Publishing database ports publicly.
-p 5432:5432exposes it on every host interface. Keep it on an internal network or bind to127.0.0.1. - Hard-coding container IPs. They change on restart. Use names.
- Confusing
EXPOSEwith-p.EXPOSEdoes not make a port reachable from the host.
Best Practices
- Create user-defined networks per application and let Compose manage them.
- Publish only the ports that must be reachable from outside, and bind to
127.0.0.1when local access is enough. - Segment networks (frontend, backend) so databases are not reachable from public-facing services.
- Use service names for configuration instead of IP addresses.
Interview Questions
1. What are the main Docker network drivers?
bridge (default, single-host private network), host (shares the host's network stack), none (no networking), overlay (multi-host), and macvlan (container appears as a device on the physical network).
2. How do containers communicate with each other?
When attached to the same user-defined network, they can reach each other by container or service name through Docker's embedded DNS, using the container port directly. On the default bridge they must use IP addresses.
3. What is the difference between EXPOSE and -p?
EXPOSE is documentation (image metadata) saying which port the application uses. -p host:container actually publishes the port on the host so external clients can connect.
4. Why can a container not reach another container using localhost?
Each container has its own network namespace, so localhost refers to the container itself. Use the other container's name on a shared network.
5. When would you use host networking?
When you need native network performance or must expose a large range of ports without mapping each one. The trade-off is losing network isolation and port-mapping flexibility, and it is Linux-oriented.
6. How does service discovery work in Docker Compose?
Compose attaches services to a project network, and Docker's DNS resolves each service name to the IPs of its containers. An app can connect to db:5432 without knowing any IP address.
Summary
- Bridge is the default driver; user-defined bridges add DNS-based name resolution and better isolation.
- Containers on the same network talk via names and container ports; publish ports only for external access.
hostremoves isolation,noneremoves connectivity.localhostinside a container never points to another container.
Continue Learning
Previous: Docker Volumes | Next: Docker Compose
Was this guide helpful?
CodeWithVenu is free to read, with no paywall. If this guide saved you time or helped you prepare, a small voluntary contribution helps me write more practical tutorials, architecture guides, and interview-prep content.