Free browser-based DevOps audit tools — no signup, nothing leaves your browser
Port open despite firewall rule — here's why and how to fix it
ports: mapping in your compose file is publicly accessible, regardless of your UFW rules.
When Docker starts a container with a port mapping, it calls iptables directly to open that port on the host. UFW is a wrapper around iptables — but Docker writes to the DOCKER chain in the NAT table, which executes before UFW's INPUT rules.
Result: your UFW status shows the port as blocked, but curl http://your-server-ip:6379 from a remote machine still connects.
services:
redis:
image: redis:7
ports:
- "6379:6379" # ← binds to 0.0.0.0 — all interfaces
services:
redis:
image: redis:7
ports:
- "127.0.0.1:6379:6379" # ← binds to localhost only
Change every ports: entry that should not be publicly accessible to use the 127.0.0.1: prefix. This makes Docker bind only to the loopback interface.
# Before - "5432:5432" - "6379:6379" - "27017:27017" # After - "127.0.0.1:5432:5432" - "127.0.0.1:6379:6379" - "127.0.0.1:27017:27017"
If a service is only accessed by other containers (not your host machine), remove the ports: block entirely. Containers on the same Docker network communicate via service name without any host port mapping.
services:
app:
image: myapp
# No ports: needed if only accessed by other containers
db:
image: postgres:15
# Remove ports: entirely — app connects via "db:5432"
# Turn off Wi-Fi, use mobile data, then: curl --connect-timeout 5 http://YOUR_SERVER_IP:6379 # Should time out or refuse connection if fixed correctly # If it connects — the port is still exposed
If you need more control, you can disable Docker's automatic iptables rules in /etc/docker/daemon.json. This requires you to manage all routing manually.
# /etc/docker/daemon.json
{
"iptables": false
}
Paste your docker-compose.yml and the Docker Auditor flags every 0.0.0.0 binding with the exact 127.0.0.1 fix — plus missing healthchecks, hardcoded secrets, and port collisions.
Open Docker Auditor →UFW and Docker both use iptables but in different chains. UFW manages the INPUT chain. Docker inserts rules into the DOCKER-USER and DOCKER chains in the NAT PREROUTING table, which is evaluated before the INPUT chain. UFW never sees the traffic.
No. Container-to-container communication uses Docker's internal network by service name (e.g. redis:6379), not the host IP. The 127.0.0.1 binding only affects traffic coming from outside the host. Containers on the same Docker network are unaffected.
Redis (6379), PostgreSQL (5432), MySQL (3306), MongoDB (27017), and Elasticsearch (9200) are the most commonly exploited. These services have no authentication by default in many Docker images and are actively scanned by automated bots within minutes of exposure.
Yes. If Traefik or nginx is running in a container with ports: "80:80" or ports: "443:443", those are intentionally public. The issue is with backend service containers (databases, caches) that should never be directly reachable from the internet.
Run sudo iptables -L DOCKER -n to see all rules Docker has added. Or run sudo ss -tlnp to see all listening ports and which process owns them. Compare against your UFW rules to find discrepancies.