For my typical usage, I need to create a container over 2 docker networks:
Pre-Info
Let's redefine something to make this clearer:
The concerned container:
workload_container
The Physical Machine LAN IP running Docker:
192.168.31.74
Networks:
test_bridge
: this is a bridge network to allowworkload_container
<=docker-dns=>other_container
amcnet
: this is a macvlan network to publish a static ip in LAN, this is for some device to directly access by LAN ip locally, for example theworkload_container
here goes192.168.31.180
Problem
- The docker network priority is not static: there seems to be no guarantee for the order binding with multiple networks in docker, this may cause mis-route
- A container that connect to both networks cannot ping the Host Machine LAN ip: 192.168.31.74
Steps to reproduce
1. Create test_bridge and amcnet networks:
docker network create test_bridge
docker network create \
--driver macvlan \
--subnet=192.168.31.0/24 \
--gateway=192.168.31.1 \
--opt parent=enp5s0 \
amcnet
2. Create dockerfile and compose.yaml file
- dockerfile:
FROM debian
RUN apt update && apt install net-tools iputils-ping -y
- compose.yaml
services:
network_test:
build: .
command: bash
privileged: true
networks:
default:
mcnet:
ipv4_address: "192.168.31.180"
networks:
default:
external: true
name: test_bridge
mcnet:
external: true
name: amcnet
3. Build & Run the container
1. ping 192.168.31.74
docker compose run \
--rm \
--build \
--remove-orphans \
network_test \
/bin/bash -c "route && ping 192.168.31.74"
output:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.31.1 0.0.0.0 UG 0 0 0 eth0
172.19.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth1
192.168.31.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
PING 192.168.31.74 (192.168.31.74) 56(84) bytes of data.
From 192.168.31.180 icmp_seq=1 Destination Host Unreachable
From 192.168.31.180 icmp_seq=2 Destination Host Unreachable
From 192.168.31.180 icmp_seq=3 Destination Host Unreachable
From 192.168.31.180 icmp_seq=4 Destination Host Unreachable
From 192.168.31.180 icmp_seq=5 Destination Host Unreachable
From 192.168.31.180 icmp_seq=6 Destination Host Unreachable
2. Add route then ping
docker compose run \
--rm \
--build \
--remove-orphans \
network_test \
/bin/bash -c "route add -net 192.168.31.0/24 gw 192.168.31.1 && route && ping 192.168.31.74"
Output:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.31.1 0.0.0.0 UG 0 0 0 eth0
172.19.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth1
192.168.31.0 192.168.31.1 255.255.255.0 UG 0 0 0 eth0
192.168.31.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
PING 192.168.31.74 (192.168.31.74) 56(84) bytes of data.
64 bytes from 192.168.31.74: icmp_seq=1 ttl=63 time=0.329 ms
64 bytes from 192.168.31.74: icmp_seq=2 ttl=63 time=0.423 ms
64 bytes from 192.168.31.74: icmp_seq=3 ttl=63 time=0.443 ms
64 bytes from 192.168.31.74: icmp_seq=4 ttl=63 time=0.466 ms
64 bytes from 192.168.31.74: icmp_seq=5 ttl=63 time=0.396 ms
64 bytes from 192.168.31.74: icmp_seq=6 ttl=63 time=0.397 ms
64 bytes from 192.168.31.74: icmp_seq=7 ttl=63 time=0.403 ms
Summary
The only difference I saw here is in route table:
192.168.31.0 192.168.31.1 255.255.255.0 UG 0 0 0 eth0
- Why
default
in route table is not working? - Why the docker network didn't respect the --gateway option since the record 192.168.31.0's gateway is 0.0.0.0(which leads to 192.168.31.180 itself)
For my typical usage, I need to create a container over 2 docker networks:
Pre-Info
Let's redefine something to make this clearer:
The concerned container:
workload_container
The Physical Machine LAN IP running Docker:
192.168.31.74
Networks:
test_bridge
: this is a bridge network to allowworkload_container
<=docker-dns=>other_container
amcnet
: this is a macvlan network to publish a static ip in LAN, this is for some device to directly access by LAN ip locally, for example theworkload_container
here goes192.168.31.180
Problem
- The docker network priority is not static: there seems to be no guarantee for the order binding with multiple networks in docker, this may cause mis-route
- A container that connect to both networks cannot ping the Host Machine LAN ip: 192.168.31.74
Steps to reproduce
1. Create test_bridge and amcnet networks:
docker network create test_bridge
docker network create \
--driver macvlan \
--subnet=192.168.31.0/24 \
--gateway=192.168.31.1 \
--opt parent=enp5s0 \
amcnet
2. Create dockerfile and compose.yaml file
- dockerfile:
FROM debian
RUN apt update && apt install net-tools iputils-ping -y
- compose.yaml
services:
network_test:
build: .
command: bash
privileged: true
networks:
default:
mcnet:
ipv4_address: "192.168.31.180"
networks:
default:
external: true
name: test_bridge
mcnet:
external: true
name: amcnet
3. Build & Run the container
1. ping 192.168.31.74
docker compose run \
--rm \
--build \
--remove-orphans \
network_test \
/bin/bash -c "route && ping 192.168.31.74"
output:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.31.1 0.0.0.0 UG 0 0 0 eth0
172.19.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth1
192.168.31.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
PING 192.168.31.74 (192.168.31.74) 56(84) bytes of data.
From 192.168.31.180 icmp_seq=1 Destination Host Unreachable
From 192.168.31.180 icmp_seq=2 Destination Host Unreachable
From 192.168.31.180 icmp_seq=3 Destination Host Unreachable
From 192.168.31.180 icmp_seq=4 Destination Host Unreachable
From 192.168.31.180 icmp_seq=5 Destination Host Unreachable
From 192.168.31.180 icmp_seq=6 Destination Host Unreachable
2. Add route then ping
docker compose run \
--rm \
--build \
--remove-orphans \
network_test \
/bin/bash -c "route add -net 192.168.31.0/24 gw 192.168.31.1 && route && ping 192.168.31.74"
Output:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.31.1 0.0.0.0 UG 0 0 0 eth0
172.19.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth1
192.168.31.0 192.168.31.1 255.255.255.0 UG 0 0 0 eth0
192.168.31.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
PING 192.168.31.74 (192.168.31.74) 56(84) bytes of data.
64 bytes from 192.168.31.74: icmp_seq=1 ttl=63 time=0.329 ms
64 bytes from 192.168.31.74: icmp_seq=2 ttl=63 time=0.423 ms
64 bytes from 192.168.31.74: icmp_seq=3 ttl=63 time=0.443 ms
64 bytes from 192.168.31.74: icmp_seq=4 ttl=63 time=0.466 ms
64 bytes from 192.168.31.74: icmp_seq=5 ttl=63 time=0.396 ms
64 bytes from 192.168.31.74: icmp_seq=6 ttl=63 time=0.397 ms
64 bytes from 192.168.31.74: icmp_seq=7 ttl=63 time=0.403 ms
Summary
The only difference I saw here is in route table:
192.168.31.0 192.168.31.1 255.255.255.0 UG 0 0 0 eth0
- Why
default
in route table is not working? - Why the docker network didn't respect the --gateway option since the record 192.168.31.0's gateway is 0.0.0.0(which leads to 192.168.31.180 itself)
1 Answer
Reset to default 0Docker picks only one default route when attaching multiple networks and typically uses the first declared network as the default. Your macvlan network’s --gateway is ignored because the container already has a default route via the bridge network. You can either reorder networks in the Compose file so the macvlan network is primary or manually add the route to force traffic out through 192.168.31.1.
amcnet
and another ismcnet
– LF-DevJourney Commented Feb 8 at 6:15ports:
to publish an individual port from the container, and then use the host's DNS name to access the service (the same way you would a non-container process)? – David Maze Commented Feb 8 at 11:53