Docker Networking

“Networking in Docker is about who can talk to whom, and on which terms.”
This write up walks through Docker network drivers, basic docker network commands, how to create and inspect networks, and how to attach containers. It also covers macvlan and none drivers with practical tests and ends with small challenge tasks.
1. Network Drivers Overview
Docker provides multiple network drivers. If you do not specify a driver when you run a container or create a network, Docker uses the bridge driver by default.
1.1 Core Network Drivers
| Network | Description |
bridge | Default driver if none is specified. Containers on the same bridge network can talk to each other but are isolated from containers on other bridge networks. All containers can reach the external network through NAT. |
host | The container shares the host network stack. Network isolation is disabled while storage and process isolation remain. Ports exposed in the container are visible on the host IP directly. |
macvlan | Attaches containers directly to the physical network. Each container gets its own MAC address on the parent interface (for example eth0) and an IP on that network. Misconfiguration can flood the network with many MACs or cause IP conflicts. |
none | Networking is disabled. Containers cannot talk to each other or the outside world. |
[!WARNING] Misconfigured macvlan can cause network issues, including too many MAC addresses seen by switches or duplicate IP addresses. Use it only when you know exactly how your upstream network behaves.
1.2 High Level View
bridge- good default for most scenarios.macvlan- used when containers must appear as real hosts on the LAN.none- used for isolation or lab scenarios when you do not want any network.
2. Working With docker network
Docker provides a dedicated subcommand to manage networks.
docker network --help
Sample output:
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks
Run 'docker network COMMAND --help' for more information on a command.
[!NOTE] In most labs you will use docker network ls, docker network create, docker network inspect, and docker network rm.
3. Default Networks
When Docker is installed, it creates three default networks.
docker network ls
# or
docker network list
Sample output:
NETWORK ID NAME DRIVER SCOPE
a49ba9341007 bridge bridge local
d12b019b2364 host host local
ddc639acd513 none null local
bridge- default user space bridge network.host- uses the host network stack.none- no networking.
4. Creating and Inspecting a Bridge Network
4.1 Create a Custom Bridge Network
docker network create mynetwork
Sample output:
4e2338e543280718087375b475bfe73de1e6019ad94b4c408a73dad3ccbe78ff
Verify:
docker network ls
Example:
NETWORK ID NAME DRIVER SCOPE
8b2369f350d5 bridge bridge local
019ff813f4f4 host host local
4e2338e54328 mynetwork bridge local
a9e2bdd51902 none null local
4.2 Inspect Network Details
Use docker inspect to see IPAM configuration, subnet, and gateway.
docker inspect mynetwork
Sample output (trimmed):
[
{
"Name": "mynetwork",
"Id": "e383473123cb3ad81a69f4842150a98b90113d0db31f1718927a09a73a5b42b9",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.19.0.0/16",
"Gateway": "172.19.0.1"
}
]
},
"Containers": {},
"Options": {},
"Labels": {}
}
]
[!TIP] docker inspect works on containers, images, and networks. For networks, focus on IPAM, Subnet, Gateway, and Containers.
5. Attaching a Container to a Bridge Network
You can attach a container to a specific network at creation time using --network.
5.1 Run a Container on mynetwork
docker run -d --name ubuntu --network mynetwork -it ubuntu:20.04
Sample output:
Unable to find image 'ubuntu:20.04' locally
20.04: Pulling from library/ubuntu
f22ccc0b8772: Pull complete
3cf8fb62ba5f: Pull complete
e80c964ece6a: Pull complete
Digest: sha256:fd25e706f3dea2a5ff705dbc3353cf37f08307798f3e360a13e9385840f73fb3
Status: Downloaded newer image for ubuntu:20.04
6de044989252172bde92f8489d721030e578f36d34e6e0a2a92b299aa3500800
5.2 Verify Container Attachment
docker inspect mynetwork
Key parts:
# docker inspect mynetwork
[
{
"Name": "mynetwork",
"Id": "3d83391642c5e601013fcbb77ebaf429b072b2100ab6d6a72bdc59c2706f76ac",
"Created": "2025-12-11T18:28:13.977528981Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"772afcae082db63e8999cf900420a6e96e1f09497e3358b2d130f04c2c086c80": {
"Name": "lucid_pascal",
"EndpointID": "806550ee3af5632117a8111673e5088a9a8c942e92c2be66daf0314d9bd13565",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
The container ubuntu now has its own IP address on mynetwork.
5.3 Test Connectivity from the Container
Run apt update inside the container via docker exec.
docker exec lucid_pascal apt update
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
Get:1 <http://archive.ubuntu.com/ubuntu> focal InRelease [265 kB]
Get:2 <http://security.ubuntu.com/ubuntu> focal-security InRelease [128 kB]
Get:3 <http://archive.ubuntu.com/ubuntu> focal-updates InRelease [128 kB]
Get:4 <http://archive.ubuntu.com/ubuntu> focal-backports InRelease [128 kB]
Get:5 <http://archive.ubuntu.com/ubuntu> focal/universe amd64 Packages [11.3 MB]
Get:6 <http://archive.ubuntu.com/ubuntu> focal/restricted amd64 Packages [33.4 kB]
Get:7 <http://archive.ubuntu.com/ubuntu> focal/multiverse amd64 Packages [177 kB]
Get:8 <http://archive.ubuntu.com/ubuntu> focal/main amd64 Packages [1275 kB]
Get:9 <http://archive.ubuntu.com/ubuntu> focal-updates/restricted amd64 Packages [4998 kB]
Get:10 <http://archive.ubuntu.com/ubuntu> focal-updates/multiverse amd64 Packages [36.8 kB]
Get:11 <http://archive.ubuntu.com/ubuntu> focal-updates/universe amd64 Packages [1599 kB]
Get:12 <http://archive.ubuntu.com/ubuntu> focal-updates/main amd64 Packages [4920 kB]
Get:13 <http://archive.ubuntu.com/ubuntu> focal-backports/main amd64 Packages [55.2 kB]
Get:14 <http://archive.ubuntu.com/ubuntu> focal-backports/universe amd64 Packages [28.6 kB]
Get:15 <http://security.ubuntu.com/ubuntu> focal-security/main amd64 Packages [4432 kB]
Get:16 <http://security.ubuntu.com/ubuntu> focal-security/multiverse amd64 Packages [33.1 kB]
Get:17 <http://security.ubuntu.com/ubuntu> focal-security/restricted amd64 Packages [4801 kB]
Get:18 <http://security.ubuntu.com/ubuntu> focal-security/universe amd64 Packages [1308 kB]
Fetched 35.7 MB in 2s (16.2 MB/s)
Reading package lists...
Building dependency tree...
Reading state information...
5 packages can be upgraded. Run 'apt list --upgradable' to see them.
Sample output (shortened):
Get:1 <http://security.ubuntu.com/ubuntu> bionic-security InRelease [88.7 kB]
Get:2 <http://archive.ubuntu.com/ubuntu> bionic InRelease [242 kB]
...
Fetched 21.7 MB in 3s (7441 kB/s)
Reading package lists...
Building dependency tree...
Reading state information...
5 packages can be upgraded. Run 'apt list --upgradable' to see them.
[!SUCCESS] Since apt update works, DNS resolution and outbound HTTP traffic both work. The container can reach the internet through Docker’s bridge network and NAT.
5.4 Clean Up
docker rm -f lucid_pascal
lucid_pascal
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
docker network ls
NETWORK ID NAME DRIVER SCOPE
1ee9fdcddb50 bridge bridge local
c7ae3f468421 host host local
3d83391642c5 mynetwork bridge local
ff657c23e1c2 none null local
docker network rm mynetwork
mynetwork
docker network ls
NETWORK ID NAME DRIVER SCOPE
1ee9fdcddb50 bridge bridge local
c7ae3f468421 host host local
ff657c23e1c2 none null local
6. macvlan Network
macvlan places containers directly on the physical network. Each container gets its own MAC and IP in the same L2 domain as the host interface.
6.1 Create a macvlan Network
docker network create --driver
bridge ipvlan macvlan overlay
docker network create --driver macvlan mymacvlan
3e9e552394578ff6584d184f0eaa0546b33907ddbba091f85e2fd2df0c4306c1
docker network list
NETWORK ID NAME DRIVER SCOPE
1ee9fdcddb50 bridge bridge local
c7ae3f468421 host host local
3e9e55239457 mymacvlan macvlan local
ff657c23e1c2 none null local
docker network inspect mymacvlan
[
{
"Name": "mymacvlan",
"Id": "3e9e552394578ff6584d184f0eaa0546b33907ddbba091f85e2fd2df0c4306c1",
"Created": "2025-12-11T18:38:35.336925861Z",
"Scope": "local",
"Driver": "macvlan",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.20.0.0/16",
"Gateway": "172.20.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
Difference Between host and macvlan Network Drivers
1. host Driver
The container shares the host’s network stack.
No virtual interfaces created.
No container level IP address. The container uses the host’s IP.
Ports exposed in the container are directly exposed on the host.
No isolation at network level.
Very low overhead because no NAT or bridge.
Use case:
Performance sensitive workloads or when you want the container to behave like a local process on the host.
2. macvlan Driver
Docker assigns the container a separate MAC address and separate IP on the physical LAN.
Container appears as a real device on the network.
Each container gets its own MAC and IP on the parent interface.
No NAT. Direct network presence.
Containers on macvlan cannot communicate with the host by default due to kernel restrictions.
Use case:
When containers must be reachable directly on the LAN as independent hosts (like appliances, routers, monitoring tools).
Quick Comparison Table
| Feature | host | macvlan |
| IP Address | Host IP (shared) | Unique IP per container |
| MAC Address | Host MAC | Unique MAC per container |
| Network Isolation | None | Containers isolated from host |
| Visibility on LAN | Same as host | Appears as separate physical device |
| NAT | No | No |
| Communication with host | Yes | No (by default) |
| Performance | Highest | High, but depends on network |
| Primary Use Case | Local host level apps | When devices must look like separate hosts |
Sample output:
8df059075f385271a681a5ddc78b6f137607117aa0a5ac1cd22159c599d804c8
List networks:
docker network list
Example:
NETWORK ID NAME DRIVER SCOPE
1201ad8119bc bridge bridge local
76876641b5a2 host host local
8df059075f38 mymacvlan macvlan local
188042442f13 none null local
6.2 Host Network View
On the host, ifconfig will show a new dm-<id> interface:
ifconfig
Relevant part:
dm-8df059075f38: flags=195<UP,BROADCAST,RUNNING,NOARP> mtu 1500
ether f6:9b:f7:8e:93:53 txqueuelen 0 (Ethernet)
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.19.0.3 netmask 255.255.0.0 broadcast 172.19.255.255
full
ifconfig
dm-3e9e55239457: flags=195<UP,BROADCAST,RUNNING,NOARP> mtu 1500
ether 8a:35:12:2e:42:a0 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
***docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:a2:34:c1:58 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0***
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450
inet 10.1.156.199 netmask 255.255.0.0 broadcast 10.1.255.255
ether 02:42:0a:01:9c:c7 txqueuelen 0 (Ethernet)
RX packets 3 bytes 158 (158.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.19.0.5 netmask 255.255.0.0 broadcast 172.19.255.255
ether 02:42:ac:13:00:05 txqueuelen 0 (Ethernet)
RX packets 2826 bytes 63471136 (63.4 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1610 bytes 115857 (115.8 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
loop txqueuelen 1000 (Local Loopback)
RX packets 28 bytes 3216 (3.2 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 28 bytes 3216 (3.2 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
6.3 Attach a Container to mymacvlan
docker run -d \\
> --name ubuntu \\
> --network mymacvlan -it \\
> ubuntu:20.04
f9787ec4440e12ab471d2f38c357df39f8adea4aa10fccef17b8df1a005f4d45
Sample output:
2a42eb64e5acb4e8dc318e64acf4380f11c37a43f088e5e1b9abd6dc4eae415d
Inspect the container network:
docker inspect ubuntu -f "{{json .NetworkSettings.Networks }}" | jq
Sample output:
{
"mymacvlan": {
"NetworkID": "8df059075f385271a681a5ddc78b6f137607117aa0a5ac1cd22159c599d804c8",
"Gateway": "172.18.0.1",
"IPAddress": "172.18.0.2",
"IPPrefixLen": 16,
"MacAddress": "02:42:ac:12:00:02"
}
}
[!QUESTION] What is the difference between bridge and macvlan drivers?
Bridge driver uses a virtual bridge and NAT. Containers get IPs on a private subnet and reach the outside world via NAT.
Macvlan puts containers directly on the physical network. Containers appear as independent hosts with their own MAC and IP on the LAN.
6.4 Clean Up
docker rm -f ubuntu
docker network rm mymacvlan
7. none Network Driver
The none driver disables networking for the container.
7.1 Run a Container With No Network
docker run -d --name ubuntu --network=none -it ubuntu:20.04
Sample output:
76f1219d23bec228e3d3c3320cfeed79eb7010865664f4fd8c55df55cc58660c
Inspect the network settings:
docker inspect ubuntu -f "{{json .NetworkSettings.Networks }}" | jq
Sample output:
{
"none": {
"NetworkID": "188042442f13fc27fb5a09ab35be331c46070f3cdf702b2a7e0d8362f01207d4",
"Gateway": "",
"IPAddress": "",
"IPPrefixLen": 0,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": ""
}
}
7.2 Test Connectivity
docker exec ubuntu apt update
Sample output (trimmed):
Err:1 <http://archive.ubuntu.com/ubuntu> bionic InRelease
Temporary failure resolving 'archive.ubuntu.com'
Err:2 <http://archive.ubuntu.com/ubuntu> bionic-updates InRelease
Temporary failure resolving 'archive.ubuntu.com'
Err:3 <http://archive.ubuntu.com/ubuntu> bionic-backports InRelease
Temporary failure resolving 'archive.ubuntu.com'
Err:4 <http://security.ubuntu.com/ubuntu> bionic-security InRelease
Temporary failure resolving 'security.ubuntu.com'
...
W: Some index files failed to download. They have been ignored, or old ones used instead.
[!FAIL] The container cannot resolve DNS or reach the internet. This is expected behavior for the none network driver.
8. Summary Comparison
| Driver | IP source | External access | Container to container | Common use case |
| bridge | Private Docker subnet | Yes, via NAT | Yes, on same bridge | Default container networking |
| host | Host network | Yes, same as host | N/A | Performance sensitive apps on bare host |
| macvlan | Physical LAN of parent iface | Yes, directly on LAN | Yes, on same macvlan | When containers must look like real hosts |
| none | None | No | No | Strong isolation or controlled lab scenarios |





