Oh boy I went down this same rabbit hole awhile ago. Here is a git repository that will explain why this happens and also offers a fix on how to modify your IP tables to ensure that docker respects the UFW.
Selfhosted
A place to share alternatives to popular online services that can be self-hosted without giving up privacy or locking you into a service you don't control.
Rules:
-
Be civil: we're here to support and learn from one another. Insults won't be tolerated. Flame wars are frowned upon.
-
No spam posting.
-
Posts have to be centered around self-hosting. There are other communities for discussing hardware or home computing. If it's not obvious why your post topic revolves around selfhosting, please include details to make it clear.
-
Don't duplicate the full text of your blog or github here. Just post the link for folks to click.
-
Submission headline should match the article title (don’t cherry-pick information from the title to fit your agenda).
-
No trolling.
Resources:
- selfh.st Newsletter and index of selfhosted software and apps
- awesome-selfhosted software
- awesome-sysadmin resources
- Self-Hosted Podcast from Jupiter Broadcasting
Any issues on the community? Report it using the report flag.
Questions? DM the mods!
With Docker, the internal network is just a bridge interface. The reason most firewall rules don't apply is a combination of:
- Containers have their own namespace including network namespace, so each container have a blank iptables just for them.
- For container communication, that goes through the FORWARD table, not the INPUT/OUTPUT ones.
- Docker adds its own rules to ensure that this works as expected.
The only thing that should be affected by the host firewall is the proxy service Docker uses to listen on a port on the host and send it to the container.
When using Docker, each container acts like an independent machine, and your host gets configured to act as a router. You can firewall Docker containers, the rules just need to be in the right place to work.
Thanks, just to clarify, even if I deny all forwards on the host using UFW, that still won't have an affect on Docker because Docker inserts its rules above UFW rules. Correct?
-
For all the mentioned cases, if your firewall blocks incoming packets by default, no one can access it, no matter what is the source of the port being open.
-
You don't configure it on the docker level, at least if you care about outside connections. If you mean from your local computer to a docker container, by default you cannot connect, unless you expose the port to the system. If you mean from other docker containers, just create your own separate network to run the container in and even docker containers cannot access the ports.
-
I usually use
netstat -tulpn
, it lists all ports, not only docker, but docker is included.docker ps
should also show all exposed ports and their mappings.
In general, all docker containers run on some internal docker network. Either the default or a custom one. The network's ports don't interfere with your own, that's why you can have 20 nginx servers running in a docker container on the same port. When you bind a port in docker, you basically create a bridge from the docker network to your PC's local network. So now anything that can connect to your PC can also connect to the service. And if you allow connection to the port from outside the network, it will work as well. Note that port forwarding on your router must be set up.
So in conclusion, to actually make a service running in docker visible to the public internet, you need to do quite a few steps!
- bind a port to your local host
- have your local firewall allow connection to the port
- have your router set up to forward connections on the port to your machine
On Linux, local firewall is usually disabled by default, but the other two steps require you to actively change the default config. And you mention that all incoming traffic is dropped using UFW, so all three parts should be covered.
I too read that it didn't work with docker but that was not my experience on Ubuntu 24.04. Maybe it's just docker desktop but I had all sorts of other issues with docker desktop and ditched it for plain docker, using lazydocker for an interface. I think one of the issues for outgoing connections at least is that IPs for the containers can change. I don't remember exactly what my setup is currently but you shouldn't have an issue opening up just specific ports mapped to a container while having default deny incoming. Not specific to containers but there are a few different Linux commands to get all ports and the processes listening on them, I used them extensively to debug my firewall setup. I can't remember them either off the top of my head but you should be able to google for your distro.
To add, you may not need to worry too much about setting up a firewall if your machine is behind a router/gateway that also has a firewall. There are arguments both ways, I would suggest researching that some. I did it because I could so why not, but I also only have wireguard exposed publicly so it may be over kill
Try tailscale for remote acess run it as a docker container. I csnt help you with the other questions.