Overview #
Docker isn’t just about images and containers. Behind containers’ ability to talk to each other, be accessed from the host, or reach the internet, there’s a layer often treated as “magic” even though it can be explained structurally: Docker networking. This layer determines whether containers can find each other, whether services inside containers are reachable from outside, and whether the multi-container applications you build are actually secure.
The classic problem new Docker users hit is docker run works, but containers can’t communicate with each other. Or the opposite: containers can talk, but the database gets accidentally exposed to the public. All of these problems stem from a half-baked understanding of networking. Once you understand Docker networking’s foundations, every configuration — docker network create, docker run --network, EXPOSE, -p, depends_on — makes sense.
This article is the foundation for the entire Network section. After reading it, you’ll understand what Docker networking is, its internal components (namespaces, veth, bridges, iptables), the differences between each network driver, when to choose which, and the workflow we’ll explore in depth in the following articles. This article is conceptual — code examples and technical details will appear in the bridge, NAT, host, none, port mapping articles, and so on.
When Do You Need to Understand Docker Networking? #
Docker networking isn’t a standalone topic. It appears in almost every scenario: from docker run nginx on a laptop to a Kubernetes cluster with hundreds of services. Signs you need to take this topic seriously:
MUST understand Docker networking if:
✓ You run more than one container
✓ Your application needs a separate database or message broker
✓ You deploy to production (cloud or on-premise)
✓ You use Docker Compose
✓ You want to secure a database service from the internet
✓ You're debugging "container can't connect" issues
✓ You're setting up CI/CD with containers
NOT yet mandatory if:
✗ You're just running a single container for experiments
✗ You use managed services (RDS, Cloud SQL) outside Docker
✗ You only run one-off batch containers
If three or more signs in the “MUST” checklist apply to you, networking is a mandatory skill, not an optional one.
The Basic Concept: What Happens When a Container Runs? #
Every Docker container, from the very first second it runs, is already interacting with the network layer inside the host. Docker doesn’t do magic — it uses mature Linux features: network namespaces, virtual ethernet pairs, bridges, and iptables. These four things are the foundation you need to understand before touching any network driver.
flowchart LR
A[docker run nginx] --> B[Docker Daemon]
B --> C[Create network namespace]
B --> D[Create veth pair]
C --> E[Container: new namespace]
D --> F[Host: veth connected to bridge]
E <-->|veth| F
F --> G[bridge: docker0 or custom]
G --> H[Host physical network]
H --> I[Internet]When you run docker run nginx, the Docker Engine does the following in sequence:
- Creates a new network namespace specifically for that container. This namespace has its own interfaces, routing table, and iptables rules.
- Creates a virtual ethernet (veth) pair — a pair of virtual interfaces connected both ways. One end goes into the container namespace (appearing as
eth0), the other end stays in the host namespace. - Connects the host-side veth end to a bridge (default
docker0, or a user-defined bridge you create). - Adds iptables rules for NAT, port forwarding, and isolation between networks.
The result: the container has its own IP address, can talk to other containers on the same bridge, and can reach the internet via NAT — all without you configuring Linux manually.
Why don’t you need to know Linux details? Because Docker hides all that complexity behind a simple CLI. But for debugging, security audits, and architecture design, understanding what happens “behind the scenes” helps a lot. This article gives you the big picture; the following articles dig deeper.
The Four Foundations of Docker Networking #
Before discussing drivers, understand the four Linux mechanisms Docker uses. All four will come up repeatedly in other articles in this section.
1. Network Namespaces #
A network namespace is network isolation at the Linux kernel level. Each namespace has:
- Its own network interfaces (eth0, lo, etc.).
- Its own routing table.
- Its own iptables rules.
A container runs inside its own namespace. As a result, container A can’t “see” container B’s interfaces — both are isolated at the kernel level.
Host Network Namespace
├── Container A Namespace (eth0: 172.17.0.2)
├── Container B Namespace (eth0: 172.17.0.3)
└── Container C Namespace (eth0: 172.17.0.4)
2. Virtual Ethernet (veth) #
veth is a pair of virtual interfaces always connected both ways — what enters one end exits the other. Docker creates a veth pair for every container:
- One end (usually named
eth0) goes into the container namespace. - The other end stays in the host namespace, connected to a bridge.
This is the “virtual cable” between container and host. Without veth, containers would be completely isolated.
3. Bridges #
A bridge is a virtual layer-2 switch in Linux. A bridge accepts connections from many veths (one per container) and forwards packets by MAC address — exactly like a physical switch.
Docker’s default bridge is named docker0. Every container run without --network connects to this bridge. You can also create custom bridges with docker network create — these are called user-defined bridges and will be a main topic in the coming articles.
4. iptables / NAT #
iptables is Linux’s firewall and NAT engine. Docker adds iptables rules for:
- MASQUERADE (source NAT) — so containers can reach the internet through the host IP.
- DNAT (destination NAT) — for port mapping (
-p 8080:80). - FORWARD rules — to allow or deny traffic between networks.
You don’t need to write iptables manually — Docker manages it. But for debugging, iptables -t nat -L -n is the first command you’ll reach for when there’s a network problem.
Network Driver Types: The Big Picture #
Docker has five built-in network drivers. Each has different characteristics and use cases. Knowing when to choose which is an important architectural decision.
| Driver | Isolation | Multi-host | Performance | Internal DNS | Use Case |
|---|---|---|---|---|---|
| bridge (default) | Yes | No | Standard | No | Local development, single-host |
| host | No | Yes (shares host) | Maximum | No | High-performance, debugging |
| none | Maximum | No | — | No | Sandboxes, batch jobs |
| overlay | Yes | Yes | Standard | Yes (Swarm) | Multi-host Swarm |
| macvlan | Yes | Yes (LAN) | High | No | Legacy integration |
A short explanation of each driver (covered in depth in their own articles):
Bridge — the most common driver. Containers connect to a virtual bridge and communicate with each other by IP or name (if user-defined). Fits almost every local development and single-host deployment case.
Host — the container uses the host’s network stack directly. No isolation, no port mapping, but the highest performance. Fits latency-sensitive workloads or those needing high network throughput.
None — a container with no network at all. Only a loopback interface. Fits batch jobs, sandboxes, or security hardening where the container must not talk to the outside.
Overlay — the multi-host driver. Containers on different hosts can communicate as if they were on the same network. Commonly used in Docker Swarm and Kubernetes.
Macvlan — containers get IP addresses directly from the host’s physical network. A container looks like a standalone device on the LAN. Fits integration with legacy systems that can’t be bridged.
Choose drivers deliberately. Many developers leave containers on the default bridge without much thought. For single-host development, that’s fine. But for multi-container architectures needing DNS, isolation, and scalability, user-defined bridges (i.e. bridges you create yourself with docker network create) are a far safer and more flexible choice. Details in the Bridge and User-defined Network articles.The Workflow: A Request from Client to Container #
To understand networking’s full role, look at a typical request flow from a client (browser) to an application inside a container, and back.
sequenceDiagram
participant C as Client
participant H as Docker Host
participant I as iptables
participant B as Bridge (docker0)
participant V as veth
participant CT as Container
C->>H: GET http://host:8080
H->>I: Receive packet on port 8080
I->>I: DNAT: 8080 -> 172.17.0.2:80
I->>B: Forward to bridge
B->>V: Look up MAC, send to veth
V->>CT: Packet reaches container eth0
CT-->>V: Response
V-->>B: Back through the bridge
B-->>I: Source NAT (host IP)
I-->>H: Packet exits
H-->>C: HTTP response reaches the clientThis flow happens on every request arriving through port mapping. Without understanding it, debugging “request timeout” or “connection refused” problems will feel like guesswork.
When starting to debug a Docker network problem, an effective check order:
docker ps— make sure the container is running and the port mapping is visible.docker logs <container>— see whether the app inside the container is erroring.docker exec <container> sh -c "wget -qO- http://target:port"— test connectivity from inside the container.iptables -t nat -L -n | grep <port>— make sure the NAT rule exists.ip link showon the host — make sure the bridge and veth are up.
Advanced Concepts You Should Know #
Before diving into the specific articles, there are three concepts you’ll encounter often. Understand their definitions here; detailed explanations follow in their own articles.
Port Mapping vs Port Exposure #
These two are often mixed up:
# EXPOSE in a Dockerfile — metadata only
EXPOSE 80
# Port mapping at run time — actually opens access
docker run -p 8080:80 nginx
EXPOSE doesn’t open a port to the host. It’s only information for documentation and tooling. What actually opens access to the host is -p / --publish. Full details in the Port Mapping & Exposure article.
NAT: Outbound and Inbound Access #
Containers use private IPs that can’t be reached from the internet. To go out (e.g. apt-get update) Docker uses MASQUERADE (SNAT). To come in (e.g. curl http://localhost:8080) Docker uses DNAT via port mapping. Full details in the NAT article.
Internal DNS: Automatic Service Discovery #
On user-defined networks, containers can call each other just by container name or service name (in Compose). No need to memorize IPs. Full details in the Internal DNS article.
Decision Tree: Choosing a Network Driver #
flowchart TD
A{Multi-host?} -- Yes --> B{Using Swarm?}
B -- Yes --> C[overlay]
B -- No --> D[bridge per host + service mesh]
A -- No --> E{Need high performance?}
E -- Yes --> F[host]
E -- No --> G{Need DNS between containers?}
G -- Yes --> H[user-defined bridge]
G -- No --> I[default bridge / none]The decision tree above isn’t a rigid rule — just a starting point. For most cases, user-defined bridges are the safe, flexible default.
Anatomy of Files and Commands You’ll Use Often #
Here are the Docker networking commands that will appear repeatedly in the coming articles. Memorize them now; they’ll feel natural later.
# List all networks on the host
docker network ls
# Inspect one network's details (subnet, gateway, connected containers)
docker network inspect <network-name>
# Create a user-defined network
docker network create my-network
# Run a container on a specific network
docker run --network my-network --name app my-image
# Connect an already-running container to another network
docker network connect my-network app
# Disconnect a container from a network
docker network disconnect my-network app
# Remove a network (if no containers are connected)
docker network rm my-network
When to use docker network create? Every time you need more than one container communicating cleanly. For a single random container that doesn’t need to talk to others, the default bridge is enough. For multi-container applications, always create a network.How the Articles in This Section Connect #
The Network section is arranged in order. Each article builds on the previous one:
| # | Article | Focus |
|---|---|---|
| 1 | Overview (you are here) | Big picture, foundational concepts |
| 2 | Bridge | Default driver, single-host |
| 3 | NAT | How containers enter and exit the network |
| 4 | Host | Containers without isolation, high performance |
| 5 | None Network | Containers with no network at all |
| 6 | Port Mapping & Exposure | -p vs EXPOSE, DNAT |
| 7 | Internal DNS | Service discovery by name |
| 8 | Container-to-Container | Communication between services |
| 9 | Network Isolation | Segmentation, security |
| 10 | User-defined Network | Best practice patterns |
You can read in order, or jump to the article you need. But for a complete understanding, the order above is the most effective.
Docker Networking and Microservices Architecture #
Ultimately, everything in this section boils down to one thing: supporting microservices architectures well. Microservices without healthy networking are fragile. Let’s look at why networking is a non-negotiable foundation.
flowchart TB
subgraph Edge["Edge Layer"]
LB[Load Balancer / Reverse Proxy]
end
subgraph App["Application Layer"]
API1[API Service]
API2[API Service]
end
subgraph Data["Data Layer"]
DB[(Database)]
Cache[(Cache)]
end
LB --> API1
LB --> API2
API1 <--> DB
API2 <--> DB
API1 <--> CacheIn the architecture above:
- API Services talk to the Database and Cache over the internal network.
- Load Balancer talks to API Services through port mapping.
- Each layer has different isolation: the edge is exposed to the internet, the data layer is completely hidden.
This is what you’ll design once you understand Docker networking. Without that understanding, all containers usually get lined up on one bridge, the database gets exposed to the host, and one security hole in a public service can be used to reach the internal database.
Basic Principles Worth Remembering #
Before diving into the specific articles, note these three principles. They’ll be your compass every time you hesitate over a networking decision.
1. Isolation is the default, not an add-on. Containers are isolated from each other by default. You’re the one who decides to open up that isolation — not the other way around. When in doubt, keep containers isolated and open only what’s genuinely needed.
2. Use names, not IPs. Container IPs can change on every restart. Container names and Compose service names are stable. Get in the habit of writing http://db:5432, not http://172.17.0.3:5432.
3. Networking is part of the security perimeter. Separating frontend and backend networks is a form of defense in depth. Services that don’t need to talk to the internet shouldn’t get access. Services meant only for internal use shouldn’t be exposed.
Most “container can’t connect” problems come from three things: (1) containers on different networks, (2) the service inside a container isn’t ready yet when another container tries to connect, (3) ports not exposed or published. All three are solvable if you understand the concepts in this section.
Summary #
- Docker networking is the layer that lets containers talk to each other, be accessed from the host, and reach the internet. It’s built on Linux features: namespaces, veth, bridges, and iptables.
- Network namespaces isolate each container’s interfaces, routing table, and iptables — that’s what keeps containers safe from each other by default.
- veth pairs are the “virtual cables” between containers and the host. Bridges are virtual switches connecting many containers. iptables handles NAT and firewalling.
- The five network drivers serve different purposes: bridge (general), host (performance), none (sandbox), overlay (multi-host), macvlan (legacy LAN).
- The default bridge fits experiments, but user-defined bridges are the serious choice for multi-container applications — internal DNS, better isolation, and explicit port mapping.
- Port mapping (
-p) differs from port exposure (EXPOSE). The former actually opens access; the latter is just documentation.- NAT is the mechanism letting containers with private IPs reach the internet (SNAT) and be reachable from the host (DNAT).
- Internal DNS on user-defined networks lets containers call each other by name instead of IP — the foundation for Docker Compose and microservices.
- For debugging, start with
docker ps→docker logs→docker execconnectivity test →iptablesrules →ip link. This order covers 90% of network problems.
← Previous: Sharing Data Between Containers Next: Bridge Network →