Docker Networking
Tools#
The netshoot Docker image is very helpful as it includes all the networking tools you might need to test with. I recently used it to mess around with the setup of docker ipvlan networking.
services:
netshoot:
image: nicolaka/netshoot
command: sleep infinity
tty: true
stdin_open: true
container_name: netshoot
environment:
- DEBIAN_FRONTEND=noninteractive
Docker ipvlan Networks#
Docker ipvlans allow each container to have a unique IP address on a specified network. This removes the need for port mapping, etc. It also allows for some flexibility with firewalls as you can create container specific firewall rules at the network edge instead of mucking around with iptables on the container host.
Note, unlike macvlans, containers on ipvlans share the same MAC address as the host server interface. This may raise some alarms depending on what security tools you have configured in your environment.
Create new ipvlan network#
docker network create -d ipvlan \
--subnet=172.17.10.0/24 \
--gateway=172.17.10.11 \
--ip-range=172.17.10.128/25 \
-o parent=ens33 \
-o ipvlan_mode=l2 \
ipvlan_net
Note: yes, I am aware the ip range CIDR is different than the subnet. This allows me to shove containers to the back half of the subnet. You can configure it to your liking.
Use external ipvlan network in containers#
Put the following in the relevant place of your docker compose file to use the network created above with a container. You can put this config in multiple compose files for other container groups as this tells the container to get its own IP address on the host network.
networks:
ipvlan_net:
external: true
services:
service_name:
networks:
ipvlan_net:
ipv4_address: 172.17.10.129
Use ipvlan with internal networks#
This is useful if you want the primary app container to communicate with the network on a specific IP, but also be able to talk to a database container that is not publicly available on the network.
Below is a snipet from a docker-compose.yml. It is not a full compose file.
networks:
ipvlan_net:
external: true
n8n_internal:
internal: true
services:
postgres:
image: postgres:16
networks:
- n8n_internal
n8n:
networks:
n8n_internal: {}
ipvlan_net:
ipv4_address: 172.17.10.129
As you can see below, the default route is the external ipvlan network. Docker container name DNS resolution still works as expected for the internal network as DNS resolution for both network types is the Docker DNS proxy by default.
fba2ae24f14e:~# ip r
default via 172.17.10.11 dev eth0
10.71.4.0/24 dev eth1 proto kernel scope link src 10.71.4.3
172.17.10.0/24 dev eth0 proto kernel scope link src 172.17.10.150
fba2ae24f14e:~# ping myapp2
PING myapp2 (10.71.4.2) 56(84) bytes of data.
64 bytes from myapp2.network_test_test_internal (10.71.4.2): icmp_seq=1 ttl=64 time=0.036 ms
64 bytes from myapp2.network_test_test_internal (10.71.4.2): icmp_seq=2 ttl=64 time=0.056 ms