Docker Keeps Ignoring Your Firewall? Here's the Fix!
So you've got UFW set up nice and tight, blocking everything you don't want... except Docker just waltzes right through it like your firewall doesn't even exist. Annoying, right?
What's Going On Here?
Docker has this lovely habit of messing with your iptables rules directly, completely ignoring whatever UFW is trying to do. It's like having a bouncer at your door while Docker sneaks in through the back window.
When you run containers with port mappings (-p 8080:80), Docker just creates its own iptables rules and publishes those ports to the world, regardless of your UFW settings. Not cool, Docker. Not cool.
Before We Start
Just need to make sure you have:
- Docker already installed and running
- UFW firewall enabled
- Basic understanding that we're about to tell Docker to stop being so pushy
Quick check if Docker is bypassing UFW:
# Check what Docker published
docker port <container_name>
# Check UFW status
sudo ufw status
# If Docker ports are accessible but not in UFW rules, you've got the problem
The Simple Fix
Step 1: Tell Docker to Chill with iptables
First, we need to create Docker's config file and tell it to stop messing with iptables:
# Create the config directory if it doesn't exist
sudo mkdir -p /etc/docker
# Edit the daemon config
sudo nano /etc/docker/daemon.json
Put this in the file:
{
"iptables": false
}
That's it! This tells Docker "hey, hands off the iptables, we'll handle the firewall ourselves."
Step 2: Restart Docker
# Restart Docker to pick up the new config
sudo systemctl restart docker
# Make sure it came back up okay
sudo systemctl status docker
Step 3: Fix Your Container Networking
Now here's the thing - your containers might not be accessible from outside anymore. That's actually what we want! But if you need certain containers to be reachable, you'll need to:
Option A: Use UFW rules (recommended)
# Allow specific ports through UFW
sudo ufw allow 8080
sudo ufw allow 3000
# Check your rules
sudo ufw status numbered
Option B: Bind to localhost only
# Instead of -p 8080:80, use:
docker run -p 127.0.0.1:8080:80 your-image
# This way it's only accessible locally
Testing It Out
Let's make sure everything works:
# Start a test container
docker run -d -p 8080:80 nginx:alpine
# Try to access it from outside
curl http://your-server-ip:8080
# Should fail if UFW is blocking it
# Allow it through UFW
sudo ufw allow 8080
# Try again
curl http://your-server-ip:8080
# Should work now
What If Things Break?
Docker Won't Start?
# Check what's wrong
sudo journalctl -u docker.service --no-pager
# Maybe the JSON syntax is wrong?
sudo nano /etc/docker/daemon.json
Containers Can't Talk to Each Other?
Docker's internal networking should still work fine, but if containers are having trouble:
# Create a custom network
docker network create mynetwork
# Run containers on the same network
docker run --network mynetwork container1
docker run --network mynetwork container2
Need to Go Back?
Easy! Just remove the config:
sudo rm /etc/docker/daemon.json
sudo systemctl restart docker
Pro Tips
Use Docker Networks
Instead of exposing everything to the world, use Docker networks:
# Create a network for your app stack
docker network create web-stack
# Run your containers on it
docker run --network web-stack -d postgres
docker run --network web-stack -d -p 127.0.0.1:3000:3000 myapp
Reverse Proxy Setup
If you're running multiple web services, use a reverse proxy:
# Only expose the reverse proxy
sudo ufw allow 80
sudo ufw allow 443
# Everything else stays internal
docker run --network web-stack -d nginx-proxy
Monitor Your Firewall
Keep an eye on what's actually allowed:
# See all UFW rules
sudo ufw status verbose
# Check actual iptables (will be more complex now)
sudo iptables -L -n
Why This Matters
Before this fix:
- Docker exposes ports directly to the internet
- UFW rules are basically ignored
- Your firewall is pretty much useless for Docker services
- Anyone can access your containers if they know the ports
After this fix:
- UFW actually controls what gets through
- You explicitly allow what you want exposed
- Much better security posture
- You're in control, not Docker
Wrapping Up
Docker's default behavior of bypassing UFW is honestly pretty annoying, but now you know how to put it in its place. Your firewall rules actually mean something again!
Quick recap:
# Create config file
sudo mkdir -p /etc/docker
echo '{"iptables": false}' | sudo tee /etc/docker/daemon.json
# Restart Docker
sudo systemctl restart docker
# Use UFW to control access
sudo ufw allow [port]
Now Docker will play nice with your firewall instead of acting like it owns the place. Much better!
