はじめに
コンテナ間をネットワークで繋ぐことができる。という知識くらいしかなかったが、それだと運用でハマるので勉強しようと思った。必要と思ったところだけ記録していきます。
事前知識
仮想ブリッジ
Dockerをインストールした時点で、docker0という名前の仮想ブリッジが生成される。
ブリッジなのでOSI参照モデルのデータリンク層(L2)で動作する。ブリッジの説明は割愛。
仮想NIC
コンテナに対して仮想NICが割り当てられる。
ネットワーク分離
各コンテナは名前空間で分離されている。
なので、ネットワークを繋いでやらないと、コンテナ間で通信ができない。
よく使うネットワーク種別
- bridge: 同一ネットワーク内でしか通信できない
- overlay: Swarmモードを有効化するなどしたばネットワークまたぎで通信可能(IPアドレス重複に注意!)
内部DNS
Dockerには内部DNSが動いており、コンテナ名での名前解決をすることができる。
同じネットワークであれば、コンテナ名で通信が可能。
基本的なコマンド
ネットワーク一覧を表示
# docker network ls
ネットワーク詳細を表示
# docker network inspect <ネットワーク名>
ネットワーク作成
bridgeネットワークとして作成されます。
docker-composeで書く場合はコマンドでcreateしなくてもよいです。
# docker network create <ネットワーク名>
ネットワーク削除
不要なネットワークを個別に削除
# docker network rm <ネットワーク名>
利用していないネットワークをまとめて削除
# docker network prune
仮想インターフェースのIPアドレスを確認
# ip a
内部ネットワーク一覧を確認
# docker network ls
NETWORK ID NAME DRIVER SCOPE
cbfda3037a97 bridge bridge local
e1b9462ba7c6 host host local
10b4e5654b78 none null local
ネットワークの種類はDRIVERに記されている。
この3つは、初期で作られるネットワークになります。
- bridge : docker-composeでネットワークを指定せずに構築すると、このネットワークが割り当てられる。このデフォルトネットワークでは、コンテナ間の名前解決ができない。名前解決させたい場合は、ユーザー定義したbridgeネットワークを作成する必要がある。
- host : ホストと同じネットワークインターフェースを使用する。ホストのポートと、コンテナのポートが一緒になるので、-pオプションを指定しなくても良くなる。(docker-composeの場合、port設定が不要)
- none : ネットワークを有しない。ループバックインターフェースのみ有する。
docker-compose.ymlへの記述
myappディレクトリに、docker-compose.ymlを保存した状態でコンテナを立てます。
/myapp
└ docker-compose.yml
ネットワークに何も記載しない場合
version: "3.8"
services:
web:
image: nginx:latest
container_name: nginx_container
hostname: web_server
ports:
- 80:80
restart: always
environment:
TZ: Asia/Tokyo
myapp_default
という、フォルダ名に_default
という名前のついたネットワークが作成されました。
defaultネットワークを作成しない方法
トップレベルのnetworksを以下のように記述。
以下の場合、デフォルトで作成されているbridgeという名前のネットワークに所属させることができます。
version: "3.8"
services:
web:
image: nginx:latest
container_name: nginx_container
hostname: web_server
ports:
- 80:80
restart: always
environment:
TZ: Asia/Tokyo
networks:
default:
name: bridge
名前付きネットワークを作成
my_networkという名前のついたネットワークを作成します。
トップレベルのnetworksでネットワークを作成しています。
subnetを宣言しない場合、docker内で空いているセグメントが自動的に付与されます。
servicesの中のコンテナ内に宣言されているnetworksでは、どのネットワークに属するかを記載しています。
ここで、ネットワーク内のどのIPアドレスを割り当てるかを記載できます。
version: "3.8"
services:
web:
image: nginx:latest
container_name: nginx_container
hostname: web_server
ports:
- 80:80
restart: always
environment:
TZ: Asia/Tokyo
networks:
my_network:
ipv4_address: 172.20.0.2
networks:
default:
name: bridge
my_network:
name: my_network
driver: bridge
ipam:
driver: default
config:
- subnet: 172.20.0.0/24
既存のネットワークを割り当てたい場合
ネットワークの設定内にexternal: true
を付けます。
networks:
default:
name: bridge
my_network:
name: my_network
driver: bridge
external: true
ipam:
driver: default
config:
- subnet: 172.20.0.0/24
注意したいこと
Dockerネットワーク内のIPアドレスと、ホストが接続できる外部サーバーのIPアドレスが重複している場合、Dockerネットワーク内のIPアドレスが優先されてしまいます。
社内ネットワークで利用する場合は、アドレス重複には注意しましょう。
また、ここで割り当てているIPアドレス(172.20.0.2)は、あくまでdocker内で使われるIPアドレスなので、Nginx(Webサーバ)にアクセスする場合はホストサーバーに割り当てられたIPアドレスからアクセスしましょう。