Dockerの内部ネットワーク構造を紐解いてみる

# はじめに
これから4回に分けてDockerとAzure Kubernetes Service（AKS）の内部ネットワーク構造に注目し、深堀りしていきます。最終回では、両者を比較し共通点・相違点についてまとめます。
第1回目は、Docker内部のネットワーク構造について整理していきます。
なお、検証環境は以下の通りです。
### 検証環境（Azure VM）
OS：Linux (ubuntu 20.04)
Size：Standard D2s v3 (2 vcpus, 8 GiB memory)

https://learn.microsoft.com/ja-jp/azure/virtual-machines/dv2-dsv2-series

# Dockerとは？
- アプリケーションとその依存関係を”コンテナ”と呼ばれる包装にパッケージ化できるプラットフォーム
- HyperVisorによるゲストOS仮想化と比べると、軽量でリソース効率的と言われている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/acb33bed-d56b-0012-18e6-a16cdcc537f3.png)

インストール方法やコマンド等は以下の記事を参考にして下さい。

https://qiita.com/maplejava/items/7429dfe7c8f33fa7f8eb

# Dockerのネットワーク構造
Dockerネットワークは以下のように3種類あります。
```
root@AZ-foo-pc28:/home/ncbpco128# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
7f81943ac8e5   bridge    bridge    local
a61dea7f7548   host      host      local
8ed41a0f9d84   none      null      local
```
## noneネットワーク
コンテナはネットワークに接続されず、外部との通信ができません。バッチジョブなど完全にネットワークから隔離された環境が必要な場合に使用します。

## hostネットワーク
コンテナはホストのネットワークスタックを直接使用します。コンテナとホストは同じIPアドレスを共有し、ポートも同じものを使用します。制約として、ホストとコンテナで同じポート番号を使用することはできません。

## bridgeネットワーク
デフォルトのネットワークモードであり一般的によく使用されます。bridgeネットワークは、以下の特徴があります。
- 同じホスト上のコンテナは**仮想ブリッジ**を介し、IPアドレスを使って相互に通信できます
- コンテナは互いに**名前解決**ができます
- コンテナが外部ネットワーク（インターネットなど）にアクセスするためには、**bridgeネットワークを通じてNATを行います**
逆に、外部からコンテナにアクセスするためには、**ポートフォワーディング**を行います。これは、ホストの特定のポートをコンテナのポートにマップすることで実現します
- bridgeネットワークは、**コンテナ間の通信をホストのネットワークから隔離します**

これらはどのように実現されているのでしょうか？

# ネットワーク構造の概要
bridgeネットワークの機能は、以下のようなLinuxカーネルの機能によって実現されています。
- network namespace
- bridge
- veth
- iptables

図で表すとこんなイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/675a4df1-6667-f89f-d9f7-fca8b4036606.png)
赤字の機能はLinuxカーネルの機能です。
### ポイント
1. 黄色部分はDockerによって作成される仮想ブリッジで、各コンテナのvethと接続されています。コンテナ間で通信するときは、このブリッジを使って通信を行います。ちなみに、ブリッジの名前はデフォルトで「docker0」です
2. コンテナごとに異なるネットワーク名前空間が割り当てられます。これにより、コンテナ間やコンテナ‐ホスト間のネットワークを隔離しています
3. コンテナのサブネットとホストのサブネットはレンジが異なります
4. コンテナがホスト外と通信するときはブリッジを経由し、ホストのeth0でIPマスカレード（iptables）されます

以降では、実際に検証環境を使用して上記の4つのポイントが本当なのか、検証してみましょう。

# 検証
Dockerをインストールした状態で、ipコマンド等を使用して色々と情報を取得しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/19a0c46a-433e-8a64-b134-959661bd0382.png)

ポイントの4以外は全てその通りになっていますね。4を確かめるために、ホスト間で通信してみましょう。

# ホスト間通信

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/292b3176-bea3-47f9-7f92-c68a414af189.png)

もう一つホストを用意し、同じようにDockerをインストールして情報を取得しました。
左側のホストのコンテナIDが6d79b5258833であるコンテナから右側の11a72050c38bのコンテナに対してpingコマンドを実行してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/898703bf-cd7f-1fb8-8bdc-cc04357ad1a0.png)

6d79b5258833のeth0でキャプチャすると、送信元IPアドレスは「172.17.0.2」となっているのでまだNATされていないですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/2daa05d1-bf7d-5b15-3434-127c99f6f512.png)

ホストのeth0でキャプチャすると、送信元IPアドレスは「az-foo-pc28.internal.cloudapp.net」となっていてホストを表しています（見慣れないホスト名なのでややこしいですがAzure VNetの機能で名前解決しています）。これは、**ブリッジからホストのeth0に転送されるときにNATされているためです。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475719/32e55776-493a-cd70-4f48-a143b92c1872.png)

これで、実際に4つのポイントを確かめることができました。

# まとめ
Dockerのbridgeネットワークモデルにおける特徴をまとめると以下の通りとなります。

1. Host内にbridgeが作られる
2. ContainerごとにNW namespaceが異なる
3. ContainerのサブネットとHostのサブネットは、レンジが異なる
4. bridgeからHostのeth0に転送されるときにNATされる

次回はAKSのkubenetネットワークモデルについて深掘りします。

# 参考

[Networking overview](https://docs.docker.com/network/)
[Docker コンテナ・ネットワークの理解 — Docker-docs-ja 19.03 ドキュメント](https://docs.docker.jp/engine/userguide/networking/dockernetworks.html)
[Dockerとホストのネットワーク on EC2 - Qiita](https://qiita.com/megmogmog1965/items/f5682de2068a79d196a2)
[Dockerのネットワークを理解するために覚えたことまとめ - Carpe Diem](https://christina04.hatenablog.com/entry/2016/07/22/193000)
[Docker network 概論 - Qiita](https://qiita.com/TsutomuNakamura/items/ed046ee21caca4a2ffd9)
[Dockerのネットワークの基礎](https://deeeet.com/writing/2014/05/11/docker-network/)
[network - 入門 Docker](https://y-ohgi.com/introduction-docker/2_component/network/)
[Dockerのブリッジネットワークについて調べました | QUARTETCOM TECH BLOG](https://tech.quartetcom.co.jp/2022/06/29/docker-bridge-network/)
[Dockerのネットワークの仕組み - sagantaf](https://sagantaf.hatenablog.com/entry/2019/12/18/234553)
[[Container Runtime Meetup] runc & User Namespaces](https://www.slideshare.net/AkihiroSuda/container-runtime-meetup-runc-user-namespaces)
[LinuxのNetns/veth/Bridge/NATで仮想ネットワーク構築](https://blog.kamijin-fanta.info/2018/12/netns/)
[Docker/Kubernetesを扱う上で必要なネットワークの基礎知識（その２） - sagantaf](https://sagantaf.hatenablog.com/entry/2019/12/14/000948#Network-Namespace)
[【連載】世界一わかりみが深いコンテナ & Docker入門 〜 その5:Dockerのネットワークってどうなってるの？ 〜 | SIOS Tech. Lab](https://tech-lab.sios.jp/archives/20179)