By enabling port forwarding and exposing, you're essentially asking docker to configure the host for it. It's likely a surprising behaviour, but seems like ufw has a bug if you have multiple chains and groups instead of just the default one.
... yes, it adds a forwarding rule. Which skips over the rest of my firewall rules. One might even say that it bypasses them.
> By enabling port forwarding and exposing, you're essentially asking docker to configure the host for it.
No, I'm asking docker to listen on that port and pass it through to the container. If I tell nginx to listen on port 80, would you expect it to take that as a "do anything you can to make sure you get port 80, including rewriting the firewall tables to ignore the rule that blocks port 80"?
That said it is a mistake to consider Docker in the same class as nginx. Docker is a system for telling the Linux kernel how to set up the environments of processes. Doing whatever it can at the absolute lowest level of abstraction the kernel offers is kind of its entire gig.
... which you explicitly asked it to do by using the -p option.
Just because it was meant to be useful and harmless doesn't mean they didn't actually bypass the firewall rules by adding their own rules.
It's annoying, but the fault lies squarely with the lack of reporting of other chains in UFW.
Clearly people want firewall rules that take priority over everything else.
Different lists are a powerful nftables feature that is used in many system services and applications for things like routing and specialized forwarding. You can't just disable that without breaking tons of software.
Instead, tools like UFW should make it clear which ports are or aren't open and what firewall rules actually apply to the current system. They exist to save users from nftables and eBPF programming, and they should work as advertised.
Ufw advertises itself with "Ufw stands for Uncomplicated Firewall, and is program for managing a netfilter firewall" not "Ufw stands for Uncomplicated Firewall, which lets you add some firewall rules but doesn't manage all of them so you need to be extra careful if you use it."
This could be solved by more tooling.
UFW, on the other hand, pretends to make firewalls simple and easy to use when they're really not. I'm not expecting UFW to start managing Docker's/K8s'/libvirtd's firewall rules, I'm just expecting them to add a section of "ports opened by other applications" that show the open ports that UFW can't control.
I'm gradually getting rid of Docker (NixOS containers powered by systemd-nspawn are more convenient for me at the moment), so I don't have any fancy networking for it - but I still run it. I have a bunch of static nftables rules for the bridge (`iifname "docker0" ct state established,related counter accept` etc.) so the containers can access what they need. And then Docker uses docker-proxy for the exposed ports (paired with appropriate firewall rules when it's not on `lo`, where I have an umbrella `iif "lo" accept`) and it seem to works just fine.