This is one that can sneak up on you even when you're not intentionally exposing a port to the internet. Docker manages iptables directly by default (you can disable it but the networking between compose services will be messed up). Another common case this can bite you is if using an iptables front-end like ufw and thinking you're exposing just the application. Then unless you bind to localhost then Posgres in this case will be exposed. My recommendation is to review iptables -L directly and where possible use firewalls closer to the perimeter (e.g. the one from your vps provider) instead of solely relying on iptables on the same node
All this talk of iptables etc is really confusing. People don't use iptables rules on servers do they? Ubuntu server has the option to enable ufw but it's disabled by default because it would be a really annoying default for a server which is by definition supposed to have services. I couldn't imagine trying to wrangle firewall rules across every box on the network vs using network segregation and firewall appliances at the edges. Is there some confusion here between running docker on your dev box vs running it on a server to intentionally run network services?
Yes, they do. At least back when I was at ZEIT, docker definitely used iptables directly. I know this because I was patching them as part of our infra that managed Docker at the time.