I was playing with Docker last week and wanted to add a firewall in front of it. This was to allow me to expose some docker containers so they could only be accessed from a restricted set of IP addresses. There are quite a few posts around that that outlines some of the deficiencies of Docker with UFW and make partial suggestions to work around this.

The main issue is that by default Docker will add iptables rules to allow external access to any ports that are exposed on docker containers. Most information I found focuses on adding –iptables=false to the docker daemon which stops Docker from allowing access to all ports through iptables. This is only half the story as there is then no info on how to enable access on a case-by-case basis. The most useful piece of information I found is a comment in an issue raised against Docker which is what the instructions below are based on.

Aims

  • Secure Docker behind Ubuntu’s Uncomplicated Firewall (UFW)
  • Avoid directly using iptables (iptables make my head hurt)

Prerequisites

  • Basic understanding of Ubuntu UFW (this link is useful too)
  • Basic understanding of Docker (all info here relates to Docker 1.8)
  • Basic Linux skills
  • Docker containers live on the 172.17.0.0/16 subnet (this is the default)

Steps

  1. start docker with –iptables=false (edit DOCKER_OPTS within /etc/default/docker – on Ubuntu and add –iptables=false)
  2. reboot the server to pick up the Docker changes
  3. Enable UFW and configure rules:
ufw allow ssh/tcp
ufw allow from 172.17.0.0/16 # allow containers to talk to each other through exposed ports on the main server
ufw enable
sudo ufw status
  1. add the following iptables rules to ufw and change the default forward policy for ufw
#if running at the command line
iptables -P FORWARD ACCEPT # allow containers to talk to each other directly
iptables -t nat -A POSTROUTING ! -o docker0 -s 172.17.0.0/16 -j MASQUERADE # allow outbound connections to the internet from containers

# otherwise
## add the following to /etc/ufw/after.rules :
# NAT table rules
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING ! -o docker0 -s 172.17.0.0/16 -j MASQUERADE # allow outbound connections to the internet from containers

## add (actually, change DROP to ACCEPT) the following to /etc/default/ufw
DEFAULT_FORWARD_POLICY="ACCEPT"
  1. reload ufw to capture the iptables rules
  2. start any docker containers
  3. add rules to UFW to allow access to the ports if appropriate (ufw allow 8080; ufw reload)

That’s it, your firewall configuration will persist between restarts keeping your docker host and containers secure.