Docker and `firewalld`: "could not resolve host" from my containers

Hi,

I switched to firewalld and when having iptables: true inside /etc/docker/daemon.json all containers mapped to the host were reachable from internet. After reading forums I saw turning it off like iptables: false and rebooting was correctly creating a docker zone for firewalld that looks like:

<?xml version="1.0" encoding="utf-8"?>
<zone version="1.0" target="ACCEPT">
  <short>docker</short>
  <description>zone for docker bridge network interfaces</description>
  <forward/>
</zone>

Then in my “public” zone I just had to allow container ports that were bound to the host. And the inbound traffic was reaching wanted my containers, great.

Unfortunately when trying a command like docker run --rm curlimages/curl https://curl.se, I end with curl: (6) Could not resolve host: curl.se. The traffic from a container cannot reach internet whereas it can go to another container (like a database), and from my server I can perform the same curl directly with OK response.

Any idea how can I solve this? I’m totally lost :confused:

Thank you,


For records, here what I had with sudo iptables -n -L when docker had iptables: true

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy DROP)
target     prot opt source               destination
DOCKER-USER  0    --  0.0.0.0/0            0.0.0.0/0
DOCKER-ISOLATION-STAGE-1  0    --  0.0.0.0/0            0.0.0.0/0
ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
DOCKER     0    --  0.0.0.0/0            0.0.0.0/0
ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0
ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0
ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
DOCKER     0    --  0.0.0.0/0            0.0.0.0/0
ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0
ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain DOCKER (2 references)
target     prot opt source               destination
ACCEPT     6    --  0.0.0.0/0            172.18.0.2           tcp dpt:8080
ACCEPT     6    --  0.0.0.0/0            172.18.0.2           tcp dpt:443
ACCEPT     6    --  0.0.0.0/0            172.18.0.2           tcp dpt:80
ACCEPT     6    --  0.0.0.0/0            172.18.0.5           tcp dpt:80
ACCEPT     6    --  0.0.0.0/0            172.18.0.7           tcp dpt:3306
ACCEPT     6    --  0.0.0.0/0            172.18.0.6           tcp dpt:5432

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target     prot opt source               destination
DOCKER-ISOLATION-STAGE-2  0    --  0.0.0.0/0            0.0.0.0/0
DOCKER-ISOLATION-STAGE-2  0    --  0.0.0.0/0            0.0.0.0/0
RETURN     0    --  0.0.0.0/0            0.0.0.0/0

Chain DOCKER-ISOLATION-STAGE-2 (2 references)
target     prot opt source               destination
DROP       0    --  0.0.0.0/0            0.0.0.0/0
DROP       0    --  0.0.0.0/0            0.0.0.0/0
RETURN     0    --  0.0.0.0/0            0.0.0.0/0

Chain DOCKER-USER (1 references)
target     prot opt source               destination
RETURN     0    --  0.0.0.0/0            0.0.0.0/0

And here what it has with iptables: false:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination 

(I know firewalld has a different mechanism, but I just wanted to bring more context)

EDIT: I posted some advancement in a reply here, but the bot has hid my message :confused:
EDIT2: my post is still hidden, so here the final “solution/workaround” I ended with: Had hard times with `firewalld` and Docker · coollabsio/coolify · Discussion #3433 · GitHub

For whatever reason after hours of search, I found a working solution 5 minutes after posting… But I would still want some explanation why it works whereas it does not with the default docker zone created by Docker.

So I had the zone with the content mentioned above, and by running:

firewall-cmd --permanent --zone=docker --change-interface=docker0
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address=172.17.0.0/16 masquerade'
firewall-cmd --reload

It does work now, the final content of `` is:

<?xml version="1.0" encoding="utf-8"?>
<zone version="1.0" target="ACCEPT">
  <short>docker</short>
  <description>zone for docker bridge network interfaces</description>
  <interface name="docker0"/>
  <forward/>
</zone>

So I’m wondering what is the purpose of each one? When removing forward it works too.

EDIT: talked too fast, it works for docker run --rm curlimages/curl https://curl.se, but not for all my containers that already exist. I tried to restart docker but it did not change… I need to investigate if I can remove them to test…
EDIT2: docker run --rm curlimages/curl https://curl.se no longer working after a reboot… and the files look the same! Oh god…
EDIT3: I noticed my failing containers are in a specific network coolify, whereas my docker run ... tests are done with network bridge. I inspected the coolify network to also allow its range of IP like done previously:

firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address=172.18.0.0/16 masquerade'
firewall-cmd --reload

But it does not work despite a docker restart :sob: .

In fact coolify tool is using a dedicated network interface with a random name, this one had to be bound to the right firewalld zone, I described all the logic: Had hard times with `firewalld` and Docker · coollabsio/coolify · Discussion #3433 · GitHub

But at the end I stopped using firewalld due to race condition of services when having cloud-init on the server, there is no official proposal so I felt uncomfortable using it: systemd unit file: possible dependency loop · Issue #414 · firewalld/firewalld · GitHub