Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
# Docker networking is messy and undocumented. Docker will create IP addresses and iptables at random times.
# This can be limited by using totally static IP addresses for network interfaces and avoiding the default network bridge.
# /etc/default/docker
# DOCKER_OPTS="--iptables=false --ipv6 --bip --fixed-cidr --fixed-cidr-v6 2a01:9000::/68"
# --bip is the host IP address of the docker0 interface
# --fixed-cidr is the CIDR subnet allocated to the docker0 interface (default network bridge)
# --fixed-cidr-v6 is the IPv6 CIDR allocated to docker0
# for IPv6 split your /64 delegated subnet into /68 subnets and allocate them to each docker-compose.yml subnet:
# docker-compose.yml
# networks:
# web:
# driver: bridge
# enable_ipv6: true
# ipam:
# driver: default
# config:
# - subnet: ""
# - subnet: "2a01:2000::/68"
# nginx:
# image: busybox
# networks:
# web:
# ipv4_address: ""
# ipv6_address: "2a01:2000::60"
table ip filter {
chain input {
iifname "br*" accept
iifname docker0 accept
chain forward {
iifname "br*" ip saddr counter accept
iifname "docker0" ip saddr counter accept
ct state established,related accept
ip daddr tcp dport https ct state new counter accept
chain nat {
type nat hook postrouting priority 100; policy accept;
oifname != "br*" ip saddr counter masquerade
chain port_forwards {
type nat hook prerouting priority -100; policy accept;
iifname eth0 ip daddr {{ ansible_default_ipv4.address }} tcp dport https counter dnat
table ip6 filter {
chain forward {
type filter hook forward priority 50; policy drop;
iifname "docker0" counter accept
iifname "br*" counter accept
# for IPv6 we don't need any of the DNAT crap, just allow https directly to the routable IP inside docker
ip6 daddr 2a01:2000::60 tcp dport https ct state new counter accept
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment