はじめに
こんにちは。孔子の80代目子孫兼技術5課の孔です。もう6月になりましたね。夏になってきて暑い日々が続いてるので、健康にも気をつけてくださいね。
前回のブログではDockerの使い方を簡単にみてみました。コマンドの仕組みのイメージがつかめたらいいかと思います。今回の話ではDockerのネットワークとボリュームについて解説します。ネットワークは、Dockerのコンテナ同士がどのようにやりとりをするのか、またホストIPをどのように経由して外部とつながるのかについて説明していきます。ボリュームは、Dockerのコンテナが共有する共通ボリュームについて説明します。
それでは、みてみましょう。Let's check it out!
Dockerにおいてのネットワーク
Dockerのネットワーク機能は、コンテナのネットワークを構成、管理するものとなります。仮想ネットワークをDockerで作成し、それぞれのネットワークにコンテナを配置することによって簡単にネットワークを構成することが可能になります。
もう少し具体的な話をするために、まずDockerのネットワーク一覧をみてみましょう表示するコマンドはdocker network lsとなります。
kong@KongnoAir docker % docker network ls NETWORK ID NAME DRIVER SCOPE 1c3d5534f8f6 bridge bridge local 3593069c284a host host local 2d216a540abf none null local
上記のシェルでNone, Host, Bridgeという単語がありますが、この三つはDockerをインストールした際にデフォルトでインストールされるネットワークとなります。それぞれのネットワーク上にコンテナを作成しながら特徴をみていきましょう。特定のネットワークにコンテナを作成するコマンドはdocker container run --net={ネットワーク名}となります。
Noneとは
Noneネットワークは、外部とも、そしてどのコンテナともつながらないネットワークを意味します。ローカル内で処理を完結したいコンテナはNoneネットワークに作成します。
kong@KongnoAir docker % docker run -it --net=none busybox sh / # ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
このように、Noneのネットワーク上に作成したコンテナはローカルネットワークしか存在してないことがわかります。他のコンテナとも、外部とも通信ができない状態です。
Hostとは
Hostネットワークは、ホストマシンとネットワークインターフェースを共有するネットワークとなります。コンテナのネットワークの設定をホストと一緒にしたい時に使います。ホストマシンのポートとコンテナのポートがマッピングされるため、コンテナでは80ポートをホストマシンの8080ポートをマッピングするようなことはできません。
Bridgeとは
Bridgeネットワークは、Dockerのコンテナ用の内部ネットワークを作成し、そのネットワークで仮想ネットワークインターフェースを作成してホストと通信のやりとりをするネットワークとなります。
こちらの図をみていただくと、ホストマシンのネットワークインターフェースであるeth0と二つのBridgeがつながってます。それぞれのBridgeにコンテナは繋がり、このBridgeを経由してホストマシンとやりとりをします。Dockerをインストールし、ネットワークの接続状況を確認してみるとdocker0というアダプターができたのがわかります。
kong@KongnoAir docker % ifconfig docker0 docker0 Link encap:Ethernet HWaddr xx:xx:xx:xx:xx:xx inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0 inet6 addr: fe80::42:a2ff:fe10:ccf7/64 Scope:Link UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:7 errors:0 dropped:0 overruns:0 frame:0 TX packets:30 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:480 (480.0 B) TX bytes:5025 (5.0 KB)
このアダプターを経由してDockerのBridgeネットワークとやりとりをしています。ちなみに、コンテナを作成する際にネットワークを指定しないとデフォルトのBridgeネットワークにアタッチされるような設定がされています。
補足:awsvpc
こちらはAWSのECSの話になりますので、興味がなければスキップで大丈夫です。ECSのタスクを定義する際にネットワークモード指定しますが、その中に上記の3つ意外にawsvpcというものが紛れ込んでます。
これはECS特有のもので、ECSクラスター上で作成される全てのタスクに固有のENIを付与するものとなります。ENIを一つ一つのタスクに付与することでSGをタスクごとに割り当てることができ、より細部までセキュリティ対策ができる仕組みになっています。より詳しい内容はドキュメントを参考にしてください。
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task-networking.html
Dokcerボリュームとは
Dockerボリュームは、コンテナ同士で同じマウントポイントを参照できる機能となります。コンテナが共通して使用するファイルがあればボリュームを作成し、コンテナがこちらのボリュームにマウントして使用することが可能になります。
例えば、DBMS(例えばMySQL)のコンテナを作成するとします。もしコンテナを作成し、そのコンテナの中にデータを保存していくと、コンテナに不具合が起きて新しいコンテナを作成しなければならない時にとても大変なことになります。せっかく簡単に環境を作成して消せるのがメリットであるDockerの良さをいかせてないですね。そのような時はデータベースが取り扱うデータをホストに保存し、コンテナで作成したDBMSはそこにマウントしておけば問題なく使えます。
さらに大事なことは、Dockerの思想に関することです。Dockerは思想として、コンテナはただのプロセスであるので一時的なものであり、その中身に差がないようなことが起きてはならないという考え方で作られました。まさにこのボリュームがその考え方を代弁するものとなりますね。
ボリュームを種類には2種類あり、Dockerデーモンがボリュームを作成してコンテナ同士で共有するスペースを作成するVolumesとホストのファイルシステム上にコンテナをマウントするBind Mountがあります。
それぞれ詳細をみてみましょう。
Volumes
Dockerデーモンがスペースを作成し、それをコンテナ同士で共有するやり方となります。作り方はdocker volume create {ボリューム名}で作成でき、こちらにコンテナをマウントする時はdocker container run -v {ボリューム名}/:{コンテナのパス}でマウントすることができます。
kong@KongnoAir docker % docker volume create test // testという名のボリューム作成 test kong@KongnoAir docker % docker volume ls DRIVER VOLUME NAME local test kong@KongnoAir docker % docker container run -it -v test:/test busybox sh // busyboxのshを起動します / # ls bin dev etc home proc root sys test tmp usr var / # cd test /test # ls // 何もない状態 /test # echo "hello from volume!!" >> hello.txt /test # ls hello.txt /test # cat hello.txt hello from volume!! /test # exit kong@KongnoAir docker % docker container run -it -v test:/test busybox sh // 新しいコンテナを作成 / # ls bin dev etc home proc root sys test tmp usr var / # cd test/ /test # ls hello.txt // 先のコンテナで作成したファイルを確認できます /test # cat hello.txt hello from volume!!
Bind mount
Bind mountは、ホストのファイルシステム上にコンテナをそのままマウントすることを指しています。別途ボリュームを用意する必要はなく、ホストマシンで修正した内容はそのままコンテナにも反映されます。こちらはコンテナを作成する際にdocker container run -v /{ホストのパス}:/{コンテナのパス}で指定可能です。ホストのパスを入力する際にスラッシュが入ってるのが違いですので、忘れずにつけましょう。
kong@KongnoAir ~ % pwd /Users/kong kong@KongnoAir ~ % echo "hello from host" >> hello.txt kong@KongnoAir ~ % cat hello.txt hello from host kong@KongnoAir ~ % docker container run -v /Users/kong:/test -it busybox sh / # exit kong@KongnoAir ~ % docker container run -v /Users/kong:/test -it --name bind_mount busybox sh // bind_mountという名前のコンテナを作成 / # ls bin dev etc home proc root sys test tmp usr var / # cd test/ /test # ls hello.txt <私のホームディレクトリにある諸々のものは省略します…> /test # cat hello.txt hello from host /test # exit kong@KongnoAir ~ % echo "hello from host again" >> hello.txt kong@KongnoAir ~ % docker container start bind_mount ~ bind_mount kong@KongnoAir ~ % docker container exec -it bind_mount sh // bind_mountという名前のコンテナのshを起動 ~ / # cat test/hello.txt hello from host hello from host again
このように、ホストマシンで加えた修正がコンテナ上にも反映されていることがわかります。
最後に
今回はネットワークとボリュームについてみてみました。どちらもコンテナ同士で連携をする際に必ず必要な知識ですのでぜひ覚えておきましょう。次はオーケストレーションサービスであるswarmについてみてみたいと思います。それでは、お元気で!