默认情况下,创建容器如果绑定了端口,则 docker 会自动修改 iptables 打开这个端口。然而 UFW 并不会显示这个规则,这就导致了不管使用 UFW 做什么限制,docker 绑定的这个端口都是开放的。
默认情况下,创建容器如果绑定了端口,则 docker 会自动修改 iptables 打开这个端口。然而 UFW(uncomplicated firewall) 并不会显示这个规则,这就导致了不管使用 UFW 做什么限制,docker 绑定的这个端口都是开放的。 可以使用 iptables -L DOCKER 查看 docker 在防火墙上开的洞,而且官方并不打算修复这个问题。 那么现在要做的就是禁止 docker 自作聪明的修改 iptables,并使用 UFW 来限制 docker 的端口开放。
在启动 UFW 之前务必添加规则允许 ssh 通过,否则... ufw allow ssh ufw allow from 172.17.0.0/16 # 允许 docker 容器之间相互访问 ufw default deny incoming ufw default allow outgoing ufw default allow routed ufw disable && ufw enable
注意:Ubuntu 16.04 之后使用 systemd 替代 upstart,所以在 /etc/default/docker 修改 DOCKER_OPTS 加上 --iptables=false 的方式不起作用了。 mkdir -p /lib/systemd/system/docker.service.d cat << EOF> /lib/systemd/system/docker.service.d/override.conf [Service] ExecStart= ExecStart=/usr/bin/dockerd EOF cat << EOF> /etc/docker/daemon.json { "hosts": ["fd://"], "dns": ["8.8.8.8", "8.8.4.4"], "iptables": false } EOF systemctl daemon-reload && systemctl restart docker 检查 docker 的启动命令 ps aux | grep docker | grep -v grep
完成上面两步之后 docker 就应该处于 UFW 的限制之下了。如果重启之后发现 docker 容器无法连接外网的话,还需要这里配置: cat << EOF>> /etc/ufw/before.rules *nat :POSTROUTING ACCEPT [0:0] -A POSTROUTING ! -o docker0 -s 172.17.0.0/16 -j MASQUERADE COMMIT EOF 检查 docker 容器是否能连接外网 docker run -it --rm alpine ping -c 1 8.8.8.8 列出 docker 的网络 docker network ls
可以使用 host 模式启动容器 docker run --net=host ...