LoginSignup
1
5

More than 1 year has passed since last update.

Dockerのネットワークの仕組み

Last updated at Posted at 2022-12-07

はじめに

今回は、Dockerのネットワークの仕組みについて解説します。対象読者はL2, L3の知識がある方となっております。

Dockerのネットワークの仕組み

先に結論を出すと、以下のような構成になっています。(公式ドキュメントより)

image.png

Ref: https://docs.docker.com/engine/tutorials/networkingcontainers

こんなのはググればそこら辺に転がっていますが、今回は実際にコマンドを叩いて確認します。

Docker起動

今回はUbuntu上にDockerを起動させました。

Dockerは起動時に以下のことを行います。実際に見ていきましょう。

  • ルーティングを作成
  • 仮想ブリッジであるdocker0を作成
  • コンテナのIPからeth0のIPに変換するのNAPTルールを作成

ルーティングの確認

新しいルーティングが追加されていますね。

$ ip route

default via 172.31.32.1 dev eth0 proto dhcp src 172.31.33.239 metric 100 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
172.31.0.2 via 172.31.32.1 dev eth0 proto dhcp src 172.31.33.239 metric 100 
172.31.32.0/20 dev eth0 proto kernel scope link src 172.31.33.239 metric 100 
172.31.32.1 dev eth0 proto dhcp scope link src 172.31.33.239 metric 100

送信元IPが172.17.0.1で送信先IPが172.17.0.0/16の場合はdocker0にパケットを送信します。

仮想ブリッジのdocker0を確認

仮想ブリッジ 1 であるdocker0が作成されていることが分かります。

$ ip address show

3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:e1:36:00:e8 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

L2スイッチの役割を果たすのでMACアドレステーブルもあるということです。brctlコマンドをインストールします。

$ sudo apt-get install bridge-utils -y

まだコンテナが立ち上がってないのでMACアドレステーブルには何も表示はされていないです。

$ brctl showmacs docker0
port no	mac addr		is local?	ageing timer

NATテーブルを確認

NATテーブルを確認することでルールが追加されているのが確認できます。

$ sudo iptables -t nat -nL

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0           

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  0.0.0.0/0            0.0.0.0/0  

送信元IPが172.17.0.0/16(Dockerのネットワーク)かつ送信先IPが0.0.0.0/0なら、送信元IPを物理NIC(eth0)のIPに変換し、外部のネットワークにアクセスできるようになります。

コンテナ起動

Nginxのコンテナを立ち上げてみます。

docker run --name nginx -d -p 80:80 nginx

コンテナが起動すると以下のことを行います。実際に見ていきましょう。

  • コンテナ専用のNetwork Namespaceとdocker0をveth2にて接続
  • 外部からのポートフォワードルールの作成

Virtual Ethernet Pairの確認

コンテナを立ち上げると、新しいインターフェースが作成されています。vethは2つのインターフェースがペアで作成され、インターフェース間で通信が行うことができます。つまり、トンネリングです。

$ ip address show

7: veth6c4af0c@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether aa:72:12:12:e8:c7 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::a872:12ff:fe12:e8c7/64 scope link 
       valid_lft forever preferred_lft forever
$ brctl show docker0

bridge name	bridge id		STP enabled	interfaces
docker0		8000.0242e13600e8	no		veth6c4af0c

コンテナ側のvethも確認していきましょう。Nginxコンテナに入ります。

docker exec -it nginx bash

ipコマンドが入っていなかったので以下のコマンドでインストールします。

apt-get update && apt-get install iproute2 -y

コンテナは自動的にIPアドレスが割り当てられており、コンテナからはeth0として見えていることが分かります。

$ ip address show

10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

NATテーブルを確認

NATテーブルを確認することでルールが追加されているのが確認できます。

$ sudo iptables -t nat -nL

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0           
MASQUERADE  tcp  --  172.17.0.2           172.17.0.2           tcp dpt:80

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 to:172.17.0.2:80

PREROUTINGにてDOCKERチェーンが呼ばれており、ホストの80番の通信をDNATしていることが分かります。

さいごに

L2スイッチを触ったことがあるものの、仮想ネットワークに関してはあまり詳しくなかったので勉強になりました。これからDockerについてさらに深ぼって行く予定です。

参考文献

  1. 仮想ブリッジとはLinux上に仮想的なL2スイッチを構成する機能です。

  2. Virtual Ethernet Deviceの略。つまり、仮想ネットワークインターフェースのことです。 vethは必ずペアで作成され、ペア間で通信が可能です。

1
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5