Configuring iptables to let Docker containers access out

I’ve got a CentOS server running Docker and I’m trying to secure it using iptables. And I can’t work out how to let containers access the internet, without their ports being accessible from outside.

I’ve stopped Docker messing with my iptables using the ‘–iptables=false’ command and am now struggling to configure iptables manually.

I want to set up the firewall so that:

  • Inputs are dropped unless I specifically open them
  • Containers can communicate with each other via the localhost connection
  • Containers can make connections to the internet to download code etc

I have the first two, but whatever I try to enable the third invalidates the first!

I have two test containers. An httpd container forwarding its web output port 3333 - and another container running Debian.

IPTables is configured with

 iptables -P INPUT DROP
 iptables -P FORWARD DROP
 iptables -P OUTPUT ACCEPT

 iptables -A INPUT -i lo -j ACCEPT

So from outside I cannot access myserver:3333.
But I can run from the host: curl localhost:3333 and have access.

I then added:

iptables -A INPUT -i docker0 -j ACCEPT

And now I can run in my debian test container curl and that works fine too.

But if I’m in the test container and try: curl I get no response.

I was reading on and tried the suggested:

iptables-A FORWARD -i docker0 -o eth0 -j ACCEPT
iptables-A FORWARD -i eth0 -o docker0 -j ACCEPT

With these I can now curl out from the test container, but this opens up 3333 to the world too!
How do I configure iptables to allow the container to access out, but prevent access in?


I think you need to add a rule to forward conected, established connections from eth0 to docker0. What you’re describing is NAT. seems inline with what I have always done.

iptables-A FORWARD -i docker0 -o eth0 -j ACCEPT

That makes sense because you want to forward all traffic from docker hosts.

iptables-A FORWARD -i eth0 -o docker0 -j ACCEPT

That’s the one which should be adjusted to look something like

iptables-A FORWARD -i eth0 -o docker0 --state RELATED,ESTABLISHED -j ACCEPT 

That allows forwarding traffic back to your docker hosts on connections that have already been established.

Perhaps I’m misunderstanding you but, if you want your containers to not expose any public ports then don’t expose them. Instead allow containers that make up you app to communicate over their own private docker network and where an external client needs to access to your app, do that via a secure reverse proxy sitting over your stack ?

As for your container reaching out to external endpoints, well you control that via your egress rules on your host, outbound proxy and other such constructs ?