Recently, I wanted to move some services that I’m running on my home server and in a VPS to docker containers. This would provide better segmentation of responsibilities, even though it would cost a bit more resources on the machines.
Because the VPS is directly connected to the net, it has a firewall. I based it on iptables, and that has been running well for a long time. Adding docker in the mix is a bit weird, because it does a lot magic with iptables that was a bit above my comfort-level (I’m a programmer, not a network-administrator!) The main thing that it does is open all the ports to all dockers that expose ports.
Luckily, the docker documentation on iptables 1 gives us a way to fix that: iptables -I DOCKER-USER -i ext_if ! -s 192.168.1.1 -j DROP
. Unfortunately, doing this, meant that I also couldn’t connect to the docker container from the host for, e.g., reverse proxying.
In order to solve this, I created a new network “ingress”, that I can attach containers to: docker network create --ip-range 10.125.0.0/16 --subnet=10.125.0.0/16 ingress
. The idea is that I can now create an explicit iptables rule for this network, allowing access from the local machine to the containers in that network. This means that attaching a container to this network (or do you attach a network to a container? 🤔) I can reverse proxy from the host!
The rule I used is: iptables -A INPUT --source 10.125.0.0/16 --destination 10.125.0.1 -j ACCEPT
. The 10.125.0.1
ip is the ingress gateway. This allows traffic to flow between the ingress network and the gateway.
In a docker-compose.yml
file, I can now add a network block:
services:
app:
...
networks:
- default
- ingress
networks:
ingress:
external: true
name: ingress
The default network is only really necessary if you have multiple services running that need to communicate with each other.
Notice how that page links to a HOWTO on Linux NAT for the 2.4 kernel. That kernel came out in 2001!↩