コンテナの構成
ネットワークを2つ用意して、pingやcurlでリクエストを送信する「クライアントコンテナ」をネットワーク1に、webサーバ用の「httpサーバ用コンテナ」をネットワーク2に設定します。
また、「ルーティング用コンテナ」をネットワーク1とネットワーク2の双方に配置し、
クライアントコンテナとhttpサーバ用コンテナ間の通信を中継します。
クライアントコンテナでping 127.19.0.2やcurl http://172.19.0.2:80 を実行し、
レスポンスが帰ってきたら成功です。
ネットワークの設定
以下のコマンドでネットワークを作成します。
$ docker network create net1
$ docker network create net2
作成したネットワークは以下のコマンドで確認できます。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
164f615dfc72 bridge bridge local
88991324c4ca host host local
78db3e751e28 net1 bridge local
130596727a1e net2 bridge local
クライアントコンテナの配置
まずネットワーク1にクライアントコンテナを配置します。
$ docker container run -it --name container1 --net net1 ubuntu:22.04
コンテナに入ったら、ip、ping、curlが使えるようにインストールしておきます。
$ apt update
$ apt install iproute2 #ipコマンド
$ apt install curl #curl
$ apt install iputils-ping net-tools #ping
ここで一旦ipコマンドを用いてネットワークインターフェースを確認してみます。
$ ip a
##出力の一部
61: eth0@if62: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:14:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.20.0.2/16 brd 172.20.255.255 scope global eth0
valid_lft forever preferred_lft forever
出力結果からeth0のipv4は172.20.0.2/16であることがわかります。
一度コンテナから出て、dockerのネットワーク設定も見てみましょう。
ネットワーク設定はdocker network inspect <ネットワーク名>で確認できます。
$ docker network inspect net1
##出力の一部
"Name": "container1",
"MacAddress": "02:42:ac:14:00:02",
"IPv4Address": "172.20.0.2/16",
"IPv6Address": ""
クライアントコンテナであるcontainer1に172.20.0.2/16が割り当てられています。
ルーティング用コンテナを配置
まずは、ネットワーク1にルーティング用コンテナを配置します。
$ docker container run -it --name router --net net1 ubuntu:22.04
次に、コンテナをネットワーク2と接続します。以下のコマンドで接続できます。
$ docker network connect net2 router
コンテナに入ってipコマンドでインターフェースを確認してみましょう。
$ ip a
## 出力の一部
63: eth0@if64: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:14:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.20.0.3/16 brd 172.20.255.255 scope global eth0
valid_lft forever preferred_lft forever
65: eth1@if66: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:15:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.21.0.2/16 brd 172.21.255.255 scope global eth1
valid_lft forever preferred_lft forever
2つのネットワーク上にインターフェースが設定されていることを確認できました。
httpサーバ用コンテナを配置
以下のコマンドでネットワーク2にwebサーバを配置します。
$ docker container run -d --name container2 --net net2 httpd
コンテナに入ってipコマンドをインストールしておきましょう。
今の状態でpingしてみる
クライアントコンテナに入って172.21.0.3へpingを飛ばしてみます。
$ ping 172.21.0.3
今の状況だと、まだルーティングが適切に設定されておらず、pingの返答が帰ってこないことがわかります。
スタティックルーティング
上記の問題を解決するために、ルーティングテーブルの設定を行います。
クライアントコンテナに、privilegedオプション付きで入ります。
そして、ip r を用いて、ルーティングの設定を行います。
$ ip r add 172.21.0.0/16 via 172.20.0.3 dev eth0
これにより、172.20.0.3をネクストホップとして、172.21.0.0/16のネットワークに接続するルールが追加されました。
httpサーバ用コンテナにもルーティングの設定を行います。
$ ip r add 172.20.0.0/16 via 172.20.0.2 dev eth0
設定できたら、クライアントコンテナから172.21.0.3へpingを飛ばすとレスポンスが来るはずです。
最後にcurlする
172.21.0.3の80番ポートにリクエストを送ってみましょう。
$ curl http://172.21.0.3:80
<html><body><h1>It works!</h1></body></html>
レスポンスボディを取得できました!