この記事は何か
イメージやコンテナなどの基本からdocker-compose、docker-machine, docker swarmなどのDocker周りの様々な概念の全体像を整理して、Dockerの仕組みを理解するための記事
対象読者
・Dockerって何?
・Dockerちょっと勉強したけどDocker compose? Docker machine? Docker Swarm? 色々ありすぎて意味不明
という方
後編では「Docker Machine、Docker Swarm」について書いて行きます。
⑦ Docker Machine
Docker Machineは、Docker Engineを搭載した仮想マシンの管理(作成、起動、停止、再起動など)をコマンドラインから実行できるツールです。
Mac OSの場合は、仮想化ソフト(Virtual Box)をドライバーに使用して、Docker Engineを搭載した仮想マシンを管理するのがDocker Machineです。
以下の図のように、PC内で複数のdocker-machineを起動して、その中でコンテナの実行などのdockerの機能が利用できるといったイメージになります。
またdocker-machineによって起動したDocker Engineが動作している仮想マシンのことをDockerホストと呼びます。
上記の図はLocalマシンの中で複数のDockerホストを立てるようなイメージになっていますが、もちろんリモートサーバにDockerホストを立てることも可能です。
参考: Docker EngineとDocker Machineの概念の違い
Docker Machineの管理コマンド
dockerホストの一覧表示
$ docker-machine ls
Dockerホストを作成
$ docker-machine create —driver virtualbox ホストマシンに付ける名前
指定した名前で新しいDockerホストを作成
—driver オプションは仮想化ソフトの指定に使用しています。
Dockerホスト起動
$ docker-machine start ホストマシン名
Dockerホスト停止
$ docker-machine stop ホストマシン名
指定したDockerホストを操作対象にするための環境変数一覧表示
$ docker-machine env ホストマシン名
この環境変数を設定することで、操作対象のdockerホストを変更できます。
DockerホストをActiveにする
$ eval $(docker-machine env ホスト仮想マシン名)
指定したDockerホストに環境変数を設定
環境変数を設定すると、指定したホスト仮想マシンがActiveになります。
反対に、docker ホストのアクティブ選択を解除するには、設定した環境変数を削除する必要があります。
Dockerホストを非アクティブにする
$ docker-machine env -u
で、環境変数削除のためのコマンドが表示
-uはunsetするというオプションです。
$ eval $(docker-machine env -u)
で現在ActiveなDockerホストを非アクティブにできます。
Dockerホストにssh接続
$ docker-machine ssh Dockerホスト名
DockerホストのIP確認
$ docker-machine ip Dockerホスト名
Dockerホスト上でコンテナ実行
Dockerホストがアクティブになっている状態で
$ docker run イメージ名
でコンテナを起動すると、ActiveなDockerホスト上でコンテナが実行されます。
クラウドサービスへのDockerホストのプロビジョニング
Docker Machineを使用して、localのコマンドラインからAWSやGCEなどにDocker Engineを搭載した仮想マシン(Dockerホスト)を作成・管理することができます。
以下に一例としてDocker Machineを使用してAWS EC2上にDockerホストを立てる手順を記述します。
- AWSのIAMからdocker-testとか適当な名前つけてアクセス認証キーを取得
アクセスキーID : -----------------
シークレットアクセスキー: ----------------------
2.その認証キーをホームディレクトリの ~/.awsディレクトリに作成したcredentialsファイルに記述した後
$ docker-machine create --driver amazonec2 --amazonec2-open-port 8000 --amazonec2-region ap-northeast-1 仮想マシン名
でdriverをamazonec2で指定した仮想マシン名で仮想マシンを立ち上げる
$ docker-machine env AWS上に立ち上げた仮想マシン名
$ eval $(docker-machine env AWS仮想マシン名)
でAWS上に立ち上げた仮想マシン(dockerホスト)をアクティブにする
$ docker run イメージ名
で、イメージからコンテナを立てる
$ docker-machine ip Dockerホスト名
で仮想マシンのIPを確認
$ docker-machine stop Dockerホスト名
で仮想マシンを停止
$ docker-machine rm Dockerホスト名
で仮想マシンを削除
のような基本的な操作も可能
ここまでの全体像
⑧ Docker Swarm
Docker Swarmは、複数台のDockerホストマシンの間でコンテナ間通信の設定・管理を自動化する手法(コンテナオーケストレーションエンジン)の1つです。
コンテナオーケストレーションエンジンには、Docker Swarmの他にもKubernetesやDC/OSなどがありますが、ここではDocker Swarmについて見て行きます。
Docker Engineの動作モードの一つにSwarm Modeがあり、Swarm Modeは
***クラスタ管理機能:***複数台のマシンをネットワーク接続してひとまとまりのシステムとして管理する機能
***オーケストレーション機能:***複数のマシンを自動で管理する機能(負荷分散、コンテナ起動など)
を持ちます。
より噛み砕いて説明すると、
Docker Swarmは
- Dockerホストマシン同士をネットワーク接続する
- その上で、「複数のホストマシン」と「その中で動作するコンテナ達」を管理・運用する様々な機能を提供する
というものです。
(中編で登場したDocker Networkは"単一Dockerホスト内"での"コンテナ同士"を接続するネットワークでした)
(1) Dockerホストマシン同士をネットワーク接続する
Docker Swarmがまずやっていることは、「複数のDockerホストマシンをネットワーク接続して、Swarmというひとまとまりのシステムにする」ということです。
具体的には、作成したSwarmにDockerホストマシンを所属させ、Swarm内のノードとなったDockerホストは、Ingressオーバーレイネットワークというネットワークで相互に接続されます。
ノードには
- コンテナを実行する役割 を持つworkerノード
- コンテナを実行する役割 + 他のノードを管理する役割 を持つmanagerノード
があります。
Swarmの管理コマンド
Swarmクラスタの作成
$ docker-machine ip [Dockerホスト名]
$ docker swarm init --advertise-addr 他のノードと通信可能なIP(上記で確認したIP)
managerノードとなるホストマシンがActiveな状態で実行してSwarmクラスタを作成する
Swarmクラスタに所属しているノード一覧表示
managerノードで
$ docker node ls
Swarmクラスタにworkerノードを追加
managerノードがActiveな状態で
$ docker swarm join-token worker
を実行し、表示された
$ docker swarm join --token [トークン] [IP]
というコマンドを
$ eval $(docker-machine env [workerノード にするdockerホスト名])
でworkerノードにするDockerホストをActiveにしてから実行
Swarmクラスタにmanagerノードを追加
上記のworkerノード追加の場合の最初のコマンドを
$ docker swarm join-token manager
にして、同じ手順で追加可能
※注意点
Swarmで使われるポート番号は
・クラスタ管理通信用:TCP 2377
・ノード間通信用:TCP/UDP 7946
・オーバーレイネットワークトラフィック用:UDP 4789
です。
Swarmに参加するDockerホスト(ノード)は必ずこれらのポートを開けておかなければならないという点に注意して下さい。
(2) 様々な管理機能
Dockerホストを繋ぐネットワークをSwarmという形で構築することによって、様々な管理機能が利用できます。
通常、Webシステムの本番環境サーバーは、1台のマシンではなく、複数台のマシンが組み合わさって、インターネットを通じてUserから送られてくるリクエストに対処しています。
この複数台のマシンをDocker machineというツールで起動・管理し、さらにDockerホストマシンを相互接続して、ひとまとまりに管理することによって、システムの本番環境で外部からのリクエストを負荷分散したり、運用に伴う様々な機能を提供するのがDocker Swarmなのです。
①ServiceとTaskによるDockerホストを跨いだコンテナ起動
まず、Docker Swarmでは、ServiceとTaskを使用することによってDockerホストをまたいでコンテナを起動・管理することができます。
Serviceとは**「どのノードでどのイメージからいくつのコンテナを起動するかを定義したもの」で、Taskとは「Serviceに基づいて実際にコンテナを実行する1つ1つの指示」**のことです。
サービスはmanagerノードで作成されます。
例えば
$ docker service create --replicas 3 nginx
で、managerノードが「nginxイメージからコンテナを3つ起動する」サービスを作成した場合は、「nginxイメージからコンテナを起動する」というTaskが3つ存在するということになります。
Serviceを使用することで、コンテナをそれぞれのDockerホストマシンで起動するのではなく、一気に起動することができ、かつ、どのコンテナをどのノードで起動するか(タスクの分配)を自動的に決定してくれます。
このようにサービスによって作成されたタスクを、各ノードに振り分ける機能をスケジューリングと言います。
特別な指定がない場合には、CPUやメモリの空きリソースの状況に従ってスケジューリングが行われるため、ユーザはどのDockerホストに配置するかなどを管理する必要がありません。
ノードのAvailability
Swarmクラスタに所属しているノードの一覧は、
$ docker node ls
コマンドで確認可能です。
各ノードは、Availabilityという状態を持っており、AvailabilityにはActive, Pause, Drainの3種類があります。
Activeは「スケジューラーがノードにタスクを割り当てることが可能な状態」
Pauseは「スケジューラーがノードにタスクを割り当てられないが、既存のタスクはそのまま実行し続ける状態」
Drainは、「スケジューラーがノードにタスクを割り当てられず、既存のタスクも終了する状態」であり、この状態によってスケジューラーにTaskを割り当てられるかどうかが決まります。
また、
$ docker node update --availability [変更したい状態] [ノード名]
で、指定したnodeのAvailabilityを変更することができます
グローバルモードとレプリカモード
レプリカモードはこれまで見てきた通り、--replicas 3
のようにサービス作成時に実行したいタスク数を指定できるモードです。
一方で、グローバルモードは、必ず1ノードで1taskを実行し、レプリカ数の指定は行わないモードです。
$ docker service create --name web3 --mode global nginx
のようにグローバルモードではレプリカ数を指定しなくても、全てのノードで1つずつタスクが実行されます。
デフォルトではレプリカモードになっています。
Serviceの管理コマンド
サービスを作成
$ docker service create --name [作成するサービス名] --replicas [レプリカ数] [起動するイメージ名]
$ docker service create --name [作成するサービス名] --constraint 'node.role==[managerまたはworker]' --replicas [レプリカ数] --detach=true [起動するイメージ名]
のように —constraintフラグをつけて、サービスを作成・起動することで、タスクの割当先ノードを指定できます。
サービスの一覧表示
$ docker service ls
サービスの詳細を表示
$ docker service inspect [サービス名]
$ docker service inspect —pretty [サービス名]
prettyフラグをつけると読みやすい形で表示されます。
作成済みのサービスの設定を変更できる
$ docker service update —publish-add 8000:80 —detach=true [サービス名]
指定したサービスを一つ前の状態に戻す
$ docker service rollback [サービス名]
指定したサービス内のプロセスを表示
$ docker service ps [サービス名]
サービスの削除
$ docker service remove [サービス名]
② ローリングアップデート
Webシステムを運営していると、システムに使用しているソフトウェアのversionをupdateしなくてはならない場合があります。
Swarmで複数のDockerホストを管理してシステム運営をしていれば、サービスのタスクをまとめて更新するのではなく、遅延時間を設定して1タスクずつupdateしていけるというのが、ローリングアップデートという機能です。
この機能によって、実行中のコンテナを残して、そのコンテナでリクエストを受けつつ、順番に別のコンテナをupdateしていくことができます。
以下でredisのアップデートの例を見ていきます。
$ docker service create --replicas 3 --name redis --update-delay 10s redis:3.0.6
のようにサービスを作成する際に、update-delayフラグでupdateの時間差を設定します。
並列更新するタスクの最大数を設定するフラグもあります。
アップデートをする場合は、
$ docker service update —image redis:3.0.7 redis
で、ローリングアップデートを開始できます。
③ Service scale / Resource management / Auto Scaling
Swarmで運用しているシステム全体の負荷が大きくなってきたら、サービス全体として起動するコンテナの数をスケールさせることができます。
$ docker service scale [サービス名]=[レプリカ数]
で指定したサービスのレプリカ数を変更できます。
もちろんオートスケールを設定することも可能です。
そもそもマシンリソース自体が足りなくなってきた場合には、マシン(AWSにおけるインスタンス)自体を追加で起動することもできます。
④ Auto Healing
大量のリクエストによる過剰な負荷がかかるなどで、Swarm内のノードがダウンしてしまった時には、そのマシンで起動していたコンテナを他のマシンが補って自動的にコンテナが起動するようAuto Healingという機能があります。
Managerノードがダウンしてしまった場合にも、複数のmanagerノードを用意することで対応可能です。
Docker composeによるServiceの作成
$ docker service create
コマンドでサービスを作成してきましが、サービスの作成すらもdocker-compose.yml
に記述することでファイルに定義した複数のサービスを自動的に作成することができます。
docker-compose.ymlには、以下のように記述します。
version: '3.4' # docker-composeの記述形式のversion指定
services: #実行するコンテナを記述していく
wordpress: #wordpressコンテナ
image: wordpress # wordpress:latestイメージを使用
ports:
- 8080:80 # ポートはマシンの8080番を外部に公開して、それをコンテナの80番ポートと繋げる
environment:
WORDPRESS_DB_PASSWORD: ----- # mysqlコンテナのPWと合わせる
deploy: # ここにDocker SwarmのService設定
replicas: 2 #レプリカ数
placement:
constraints:
- node.role == worker # workerノードのみで実行
depends_on:
- mysql # mysqlから先に起動する設定
mysql: #mysqlコンテナ
image: mysql:5.7 # 使用するイメージ指定
environment:
MYSQL_ROOT_PASSWORD: ----- # パスワード設定
volumes:
- mysql_vol:/var/lib/mysql # mysql_volというvolumeを作成して、コンテナ上の指定したディレクトリにマウント
deploy: # ここにDocker SwarmのService設定
replicas: 1
placement:
constraints:
- node.role == manager # managerノードで実行
volumes:
mysql_vol: #volumeの定義
その後、以下のように$ docker stack deploy
コマンドを使用して、docker-compose.ymlファイルからSwarmにおけるサービスを作成することができます。
$ docker stack deploy --compose-file docker-compose.yml(composeファイルの指定) [作成するスタック名]
スタック名は作成されるサービス名の接頭辞になります。
stackの管理コマンド
スタックを作成する
$ docker stack deploy --compose-file [composeファイルの名] [作成するスタック名]
スタックの一覧表示
$ docker stack ls
スタックの削除
$ docker stack remove スタック名