I'm worried about accidentally exposing my internal database ports to the public internet when using the -p flag in Docker. Sometimes I only want a port to be accessible by other containers or by the host itself, not by the entire world. What is the syntax to bind a port to a specific IP address, and how can I verify that my Docker networking isn't bypassing my UFW firewall?
3 answers
You can also use the --internal flag when creating a network to completely disable its access to the outside world (no default gateway).
The most common mistake is using -p 8080:8080, which by default binds to 0.0.0.0 (all interfaces). To restrict this to the host only, use -p 127.0.0.1:8080:8080. This ensures the port is only reachable from the local machine. Regarding the firewall, Docker manages its own iptables chains which often bypass UFW. To fix this, you should either use a tool like ufw-docker or configure the Docker daemon with "iptables": false in daemon.json, though the latter can break container-to-container communication if not handled carefully. Always verify your exposure with a port scanner like nmap from an external machine.
Have you considered using an internal-only Docker network without any port mapping at all for your database, and only exposing the web frontend?
David, that’s actually the cleanest architecture. I’ve now moved the database to a "backend" bridge network with no ports exposed. Only the API container is connected to both the "backend" and "frontend" networks. Sandra, binding to 127.0.0.1 saved me from a major security headache on our staging server. I also installed the ufw-docker script you mentioned, and it’s finally letting me manage container access via standard UFW commands instead of digging into raw iptables rules.
Karen's suggestion is the ultimate "air-gap" for containers. It's perfect for processing sensitive data that should never touch the public internet.