Docker containers cannot connect to internet in Fedora 32?
Event though the OP found a workaround for his problem and closed this issue, he did not find the root issue. The fact that Docker's default bridged network bridge
is connected to the internet and airflowsetup_default
is not suggests that something is wrong with Docker networking setup.
I did some research and it turns Fedora 32 decided it doesn't really care if Docker works on it or not.
It's not even possible to install Docker in a way described in the documentation and if you install the package provided by Fedora it still doesn't work correctly - more information on that issue can be found here, here and here.
The main issue is that there is no internet connectivity inside the containers if they are connected to any custom bridged network - whether it was created using docker network create
or by docker-compose.
The reason why is simple - Docker assumes that the firewall used by the OS is iptables, but Fedora 32 uses firewalld by default. That means Docker cannot configure the firewall manually - it has to be configured by hand.
For reference purposes I will first describe how to set up Docker on a clean Fedora 32 installation.
First run the following commands:
sudo grubby --update-kernel=ALL --args="systemd.unified_cgroup_hierarchy=0"
sudo groupadd docker
sudo usermod -aG docker $USER
This will configure cgroups to be compatible with Docker daemon and allow your user to use Docker CLI without sudo.
Next restart your system to apply changes and run:
sudo dnf install -y moby-engine docker-compose nano
sudo systemctl enable docker
sudo systemctl start docker
to install and enable Docker.
Now go to the directory that contains your docker-compose.yml
and run docker-compose up -d
. Yuo should see docker-compose
creating a network for you and then creating the container. If your container requires internet connection on startup (like the OP's) it will fail to start.
Now run sudo iptables-save | grep DOCKER
and you should see something like:
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o br-b56fa303f315 -j DOCKER
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-b56fa303f315 ! -o br-b56fa303f315 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o br-b56fa303f315 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A DOCKER -i docker0 -j RETURN
-A DOCKER -i br-b56fa303f315 -j RETURN
docker0
is Docker's default bridged network, while br-b56fa303f315
is the new network created by docker-compose
(yours may have a different name). If your OS were using iptables
everything would work as expected, but it does not, so we need to check the configuration of docker0
in firewalld
.
Run firewall-cmd --get-active-zones
and you'll get something similar to:
docker
interfaces: docker0
public
interfaces: eth0 eth1
You can see that bridge
network is in docker
zone, but the new network is not. In fact it's not listed at all, which means it's in the default zone. You can check what that is by running firewall-cmd --get-default-zone
. On a clean install of Fedora 32 it's public
.
So run (remember to replace br-b56fa303f315
with your interface name):
sudo firewall-cmd --zone=docker --add-interface=br-b56fa303f315
run docker-compose up -d
if your service failed to start previously and voila - your container has network connectivity.
Unfortunately if your restart your system it'll lose that connectivity again.
You can prevent that by using:
sudo firewall-cmd --permanent --zone=docker --add-interface=br-b56fa303f315
sudo firewall-cmd --reload
However if you create any new networks or recreate existing ones (for example by running docker-compose down
and then docker-compose up -d
again) you'll have to repeat the process.
So what is the solution to this problem?
First, write down all network interfaces that are currently attached to the default zone - in this example eth0
and eth1
.
Then run the following (replacing public
with your default zone's name)
sudo firewall-cmd --set-default-zone=docker
sudo firewall-cmd --permanent --zone=public --add-interface=eth0
sudo firewall-cmd --permanent --zone=public --add-interface=eth1
sudo firewall-cmd --reload
Now the interfaces that were previously in your default zone should be there again, but all the new interfaces (and therefore all the new Docker networks) will be automatically added to docker
zone, which will give them full network connectivity.