TL;DR
- Docker上のコンテナがインターネットもしくは他コンテナとIPで通信するにはIPフォワーディングの仕組みを使う。
- dockerd立ち上げ時に
--ip_forward=false
を指定しない場合、デフォルト動作でIPフォワーディングの設定がされてない場合設定をしてくれる。 - ただしdockerd起動後にCentOSで
systemctl restart network
などを行いIPフォワーディングの設定がオフになっても自動でオンに戻ったりはしないので気をつけよう。- インターネット接続をするコンテナを動かすサーバーでは
/etc/sysctl.conf
にnet.ipv4.ip_forward = 1
と書いて必ずIPフォワーディングを有効にする、もしくは--net=host
を指定してホストネットワークを使うなど。
- インターネット接続をするコンテナを動かすサーバーでは
背景
先日、Kubernetesクラスターのノードの静的ルーティングを変更する必要があり、ルーティング設定ファイルを編集した後に systemctl restart network
を行いました。
するとなぜかコンテナからインターネットに接続できなくなり、焦ってOS再起動を行いコンテナを再立ち上げしたところ再びつながるようになりました。
その後 /var/log/messages
などを調べてみるとnetworkサービスの再起動によりIPフォワーディングの設定がリセットされていたことがわかりました。
実験
実際に試してみました。
動作確認環境
以下の環境で確認を行いました。
- Ubuntu 18.04 on VirtualBox
- Docker-ce 18.09.4
手順
まずdockerdを止めた状態でOSを起動し、IPフォワーディングが無効になっていることを確認します。
$ sudo sysctl -a 2>/dev/null| grep -E 'net.*forward'
net.ipv4.conf.all.forwarding = 0
net.ipv4.conf.all.mc_forwarding = 0
net.ipv4.conf.default.forwarding = 0
net.ipv4.conf.default.mc_forwarding = 0
net.ipv4.conf.enp0s3.forwarding = 0
net.ipv4.conf.enp0s3.mc_forwarding = 0
net.ipv4.conf.lo.forwarding = 0
net.ipv4.conf.lo.mc_forwarding = 0
net.ipv4.ip_forward = 0
net.ipv4.ip_forward_use_pmtu = 0
net.ipv6.conf.all.forwarding = 0
net.ipv6.conf.all.mc_forwarding = 0
net.ipv6.conf.default.forwarding = 0
net.ipv6.conf.default.mc_forwarding = 0
net.ipv6.conf.enp0s3.forwarding = 0
net.ipv6.conf.enp0s3.mc_forwarding = 0
net.ipv6.conf.lo.forwarding = 0
net.ipv6.conf.lo.mc_forwarding = 0
確認したらdockerdを起動します。引数に --ip_forward=false
をつけていない普通の状態で立ち上げます。
$ sudo systemctl start docker
$ sudo sysctl -a 2>/dev/null| grep -E 'net.*forward'
net.ipv4.conf.all.forwarding = 1
net.ipv4.conf.all.mc_forwarding = 0
net.ipv4.conf.default.forwarding = 1
net.ipv4.conf.default.mc_forwarding = 0
net.ipv4.conf.docker0.forwarding = 1
net.ipv4.conf.docker0.mc_forwarding = 0
net.ipv4.conf.enp0s3.forwarding = 1
net.ipv4.conf.enp0s3.mc_forwarding = 0
net.ipv4.conf.lo.forwarding = 1
net.ipv4.conf.lo.mc_forwarding = 0
net.ipv4.ip_forward = 1
net.ipv4.ip_forward_use_pmtu = 0
net.ipv6.conf.all.forwarding = 0
net.ipv6.conf.all.mc_forwarding = 0
net.ipv6.conf.default.forwarding = 0
net.ipv6.conf.default.mc_forwarding = 0
net.ipv6.conf.docker0.forwarding = 0
net.ipv6.conf.docker0.mc_forwarding = 0
net.ipv6.conf.enp0s3.forwarding = 0
net.ipv6.conf.enp0s3.mc_forwarding = 0
net.ipv6.conf.lo.forwarding = 0
net.ipv6.conf.lo.mc_forwarding = 0
IPフォワーディングが有効になりました。
UbuntuではCentOSなどのように sudo systemctl restart network.service
ではなく sudo systemctl restart systemd-networkd
なので再起動してみたのですが、IPフォワーディング設定はリセットされてないようでした。
なので明示的にオフにしてみます。
$ sudo sysctl -w net.ipv4.ip_forward=0
$ docker run --rm -it alpine
WARNING: IPv4 forwarding is disabled. Networking will not work.
IPフォワーディングが無効の状態で立ち上げたコンテナからはインターネットに接続できず、apkパッケージのインストールなどができなくなっていました。