I just tried out Docker. It is awesome but seems not work nicely with ufw. By default, docker will manipulate the iptables a little bit. The outcome is not a bug but not what I expected. For more details you can read The dangers of UFW + Docker
My goal is to set up a system like
Host (running ufw) -> docker container 1 - nginx (as a reverse proxy)
-> docker container 2 - node web 1
-> docker container 3 - node web 2
-> .......
I want to manage the incoming traffic (e.g. restrict access) through ufw therefore I don't want docker to touch my iptables. Here is my test
Environment:
--iptables=false
was added to the Docker daemon.First Attempt
docker run --name ghost -v /home/xxxx/ghost_content:/var/lib/ghost -d ghost
docker run --name nginx -p 80:80 -v /home/xxxx/nginx_site_enable:/etc/nginx/conf.d:ro --link ghost:ghost -d nginx
No luck. The first command is fine but the second command will throw an error
Error response from daemon: Cannot start container
Second Attempt
Then I found this: unable to link containers with --iptables=false #12701
After running the following command, everything looks OK.
sudo iptables -N DOCKER
However, I noticed that I can not establish any outbound connections inside containers. For example:
xxxxg@ubuntu:~$ sudo docker exec -t -i nginx /bin/bash
root@b0d33f22d3f4:/# ping 74.125.21.147
PING 74.125.21.147 (74.125.21.147): 56 data bytes
^C--- 74.125.21.147 ping statistics ---
35 packets transmitted, 0 packets received, 100% packet loss
root@b0d33f22d3f4:/#
If I remove --iptables=false
from the Docker daemon, then the internet connection of containers will be back to normal but the ufw will not work 'properly' (well...by my definition).
So, what is the best practice of docker + ufw? Can anyone provide some help?
I've had such problem like months ago and lately decided to describe the issue along with the solution on my blog. Here's the shortcut.
Using --iptables=false
won't help you much with the case you described. It's simply not enough here. By default, none of your containers can do any outgoing connection.
There's a small step you're omitting on your way to have containers behind UFW here. You can use --iptables=false
or create /etc/docker/daemon.json
file with content as follows
{
"iptables": false
}
the result will be the same, but the latter option requires you to restart whole docker service with service docker restart
or even do a reboot if docker had a chance to add iptables rules before you disabled this function.
When it's done, just do two more things:
$ sed -i -e 's/DEFAULT_FORWARD_POLICY="DROP"/DEFAULT_FORWARD_POLICY="ACCEPT"/g' /etc/default/ufw
$ ufw reload
so you set up default forward policy in UFW for accept, and use:
$ iptables -t nat -A POSTROUTING ! -o docker0 -s 172.17.0.0/16 -j MASQUERADE
That way what you're achieving is disabling docker messy behavior in your iptables rules and at the same time docker is provided with necessary routing so containers will do outgoing connections just fine. UFW rules will be still restricted from this point on, though.
Hope this resolves the issue for you and any that gets here in search of an answer.
I described the problem and solution more comprehensively at https://www.mkubaczyk.com/2017/09/05/force-docker-not-bypass-ufw-rules-ubuntu-16-04/