A decides which containers can talk to each other and which IP each one gets. Docker creates three networks when it starts:
docker network ls
NETWORK ID NAME DRIVER SCOPE
6133d93a1424 bridge bridge local
d903b86f388c host host local
4f0bd8326f81 none null local| Network | What a container gets |
|---|---|
bridge | The default. A private IP on a virtual switch (docker0) on the host. |
host | No isolation. The container uses the host's network interfaces directly. |
none | Only a loopback interface. No network access. |
The default bridge
Every container started without --network joins bridge:
Docker host
┌────────────────────────────────────────────┐
│ docker0 172.17.0.1 (gateway) │
│ │ │
│ ├── web 172.17.0.2 │
│ └── cache 172.17.0.3 │
└────────────────────────────────────────────┘Read the subnet and gateway:
docker network inspect --format '{{json .IPAM.Config}}' bridge[{"Subnet":"172.17.0.0/16","Gateway":"172.17.0.1"}]The full docker network inspect bridge also lists every attached container under Containers, with its IP.
A container's IP
docker inspect --format '{{.NetworkSettings.IPAddress}}' web172.17.0.2IPs are assigned when a container starts. A container that is recreated, or started after others, can get a different IP. Do not hard-code them.
Reaching a container on the default bridge
| From | 172.17.0.2 | web (name) |
|---|---|---|
Another container on bridge | works | fails |
| The Docker host | works (Linux) | fails |
By IP from another container:
docker run --rm alpine:3.20 ping -c 1 172.17.0.2PING 172.17.0.2 (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.080 msBy name:
docker run --rm alpine:3.20 ping -c 1 webping: bad address 'web'The default bridge has no name resolution for containers. That is the main reason to create your own network, which the next lesson covers.
From the host, the bridge IP works even though web publishes no port:
curl -s 172.17.0.2 | head -4<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>