How to Configure UFW (Uncomplicated Firewall) for Docker Containers in Ubuntu

The UFW and Docker Conflict

Ubuntu server administrators rely on UFW (Uncomplicated Firewall) for its simplicity and ease of use when locking down incoming connections. A standard security practice is to configure UFW to deny incoming by default, and only allow specific ports like 22 for SSH and 443 for HTTPS.

However, when you install Docker on Ubuntu, it creates a massive, often unexpected security hole. Docker manipulates iptables (the underlying routing engine that UFW also uses) directly to facilitate container networking. Because Docker’s rules evaluate before UFW’s rules, any port you expose in a Docker container (e.g., using -p 8080:80) completely bypasses UFW. Even if UFW says port 8080 is blocked, your container will be accessible to the public internet.

The Solution: Modifying Docker’s Iptables Behavior

There are several approaches to fixing this flaw, such as binding Docker containers explicitly to 127.0.0.1, but the most robust method is to patch the UFW routing chains so that Docker traffic respects the UFW firewall rules.

Step 1: Download the UFW-Docker Script

Instead of manually writing complex iptables routing chains, the open-source community maintains a widely accepted script called ufw-docker that automatically patches the integration.

First, download the script using wget:

sudo wget -O /usr/local/bin/ufw-docker https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker

Make the script executable:

sudo chmod +x /usr/local/bin/ufw-docker

Step 2: Install the Patch

Run the installation command. This command appends the necessary routing logic into the /etc/ufw/after.rules file.

sudo ufw-docker install

After installing, you must restart UFW to apply the changes:

sudo systemctl restart ufw

How to Expose Docker Containers Securely

Now that the patch is active, if you run a Docker container (for example, a database on port 3306), it will not be accessible from the outside world, even if you used the -p 3306:3306 flag. UFW is successfully blocking it.

To safely expose that specific container port, you must now use the ufw-docker command instead of the standard ufw allow command.

Exposing a Port to the Public

If you want to open port 80 for an Nginx container named my_web_server to the entire internet:

sudo ufw-docker allow my_web_server 80

Exposing a Port to a Specific IP Address

If you have a MySQL container named my_database on port 3306, and you only want your application server at 192.168.1.100 to access it:

sudo ufw-docker allow my_database 3306/tcp -s 192.168.1.100

Checking Status

To view the current UFW rules that apply specifically to Docker containers, run:

sudo ufw-docker status

Conclusion

The silent bypass of UFW by Docker is one of the most common vulnerabilities found in self-hosted Ubuntu servers. By implementing the ufw-docker patch, you restore the intended behavior of your firewall, ensuring that you have explicit, centralized control over which containerized services are exposed to the internet.

RELATED POSTS

  • How to Secure an Nginx Web Server with Let’s Encrypt and UFW on Ubuntu
  • How to Install and Configure the Postfix Mail Server on Ubuntu
  • How to Configure Auditd (Linux Audit Daemon) for Security Compliance
  • How to Detect Rootkits on Linux Using rkhunter
  • How to Change the Default Gateway in Linux Using the ip route Command
  • Get the best tech tips delivered straight to your inbox.

    Join thousands of readers mastering Apple, Google, Microsoft, and Linux.