Part 5:スタック¶
必要条件¶
- Docker バージョン 1.13 以上のインストール
- Part 4 を入手。
- Part 1 の概要を読んでいること
- Part 2 のコンテナの作成方法学んでいること
- 自分で作成した
friendlyhelloイメージを レジストリに送信 して公開済みなのを確認します。ここでは、この共有イメージを使います。 - イメージをコンテナとしてデプロイできるのを確認します。次のコマンドを実行しますが、
ユーザ名とリポジトリタグは皆さんのものに置き換えます。コマンドはdocker run -p 80:80 ユーザ名/リポジトリ:タグです。そしてhttp://localhost/を表示します。 - Part 3 で扱った
docker-compose.ymlのコピーを持っていること - Part 4 でセットアップしたマシンが実行中かつ準備できていること。確認には
docker-machine lsを実行。マシンが停止している場合は、マネージャをdocker-machine start myvm1で起動し、ワーカをdocker-machine start myvm2で起動 - Part 4 で作成した swarm (クラスタのこと)が実行中かつ準備できていること。確認には
docker-machine ssh myvm1 "docker node ls"を実行。swarm が起動中であれば、いずれのノードも status (状態)はready(準備完了)。そうでなければ、swarm を再度初期化し、ワーカを swram としてセットアップ します。
はじめに¶
Part 4 では、 swarm のセットアップ方法を学びました。swarm とは Docker を実行しているマシンのクラスタであり、アプリケーションを複数のマシン上へ一斉にデプロイします。
この Part 5 では、 スタック(stack) という分散アプリケーション階層の頂上に辿り着きました。スタックは相互関係を持つサービスのグループであり、依存関係を共有します。そして、同時にオーケストレート(訳者注;複数のサーバ上で一斉に挙動する)やスケール(訳者注;サービスの拡大および縮小)します。1つのスタックでアプリケーション全体の能力を定義し、機能全体をコード化します(複雑なアプリケーションであれば、複数のスタックを使うことになるでしょう)
良いお知らせがあります。スタックに関する技術的な内容は Part 3 で既に学んだとおり、 Compose ファイルを作成し、 docker stack deploy を実行するだけです。しかし、これまで行ったことは1つのホスト上で1つのサービス・スタックを動かしただけであり、プロダクションではあまり見ない環境です。ここでは従来の学びに加え、複数のマシン上で複数の関連サービスをお互いに作成し、実行しましょう。
ここまでおつかれさまでした。あと一息です!
新しいサービスの追加と再デプロイ¶
サービスは docker-compose.yml に追加するだけであり、とても簡単です。まず、swarm でコンテナのスケジューリングを調べるために、自由に使える可視化サービスを追加しましょう。
- エディタで
docker-compose.ymlを開き、内容を以下の通りに書き換えます。username/repo:tagの部分は、皆さんのイメージにあわせてください。
version: "3"
services:
web:
# username/repo:tag は皆さんの名前とイメージにあわせて書き換えます
image: username/repo:tag
deploy:
replicas: 5
restart_policy:
condition: on-failure
resources:
limits:
cpus: "0.1"
memory: 50M
ports:
- "80:80"
networks:
- webnet
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
networks:
- webnet
networks:
webnet:
新しく追加したのは visualizer という名前の web と対となるサービスです。そして、ここでは新しい2つのものがあります。1つは volumes キーであり、ビジュアライザが Docker ホスト側のソケットファイルにアクセスするためです。それと、 placement キーはサービスが swarm マネージャのみでしか動作しないよう指定しています。ワーカーでは決して動きません。これは Docker によって作られたオープンソース・プロジェクト であり、 swarm 上で実行している Docker サービスを図で表示するものです。
placment 制限(constraint)とボリュームの詳細は後述します。
- 新しい
docker-compose.ymlを swarm マネージャmyvm1にコピーします。
docker-machine scp docker-compose.yml myvm1:~
- マネージャ上で
docker stack deployコマンドを再度実行し、更新が必要なサービスはアップデートが始まります。
$ docker-machine ssh myvm1 "docker stack deploy -c docker-compose.yml getstartedlab"
Updating service getstartedlab_web (id: angi1bf5e4to03qu9f93trnxm)
Updating service getstartedlab_visualizer (id: l9mnwkeq2jiononb5ihz9u7a4)
- ビジュアライザを確認します。
Compose ファイルにあった visualizer はポート 8080 で動作します。 docker-machine ls を実行して、実行中のノードの IP アドレス1つを確認します。いずれかの IP アドレスの1つのポート 8080 を開くと、ビジュアライザの動作を確認できます。
(スクリーンショット;todo)
期待した通り、マネージャ上では visualizer のコピーが動作し、 web の5つのインスタンスは swarm 全体に展開しています。図の内容が正しいかどうかを確認するには、 docker stack ps <stack> を実行します。
docker-machine ssh myvm1 "docker stack ps getstartedlab"
ビジュアライザはスタンドアローンのサービスのため、スタック上のあらゆるサービスと実行できます。また、その他のものと依存関係はありません。次は依存関係を 持つ サービスを作成しましょう。Redis サービスは来訪者カウンタ機能を提供します。
データの保持¶
同じワークフローを通して、今度はアプリのデータを保管する Redis データベースを追加しましょう。
- 末尾に Redis サービスを追加した、新しい
docker-compose.ymlファイルを保存します。ただし、username/repo:tagは皆さんのイメージに置き換えてください。
version: "3"
services:
web:
# username/repo:tag は皆さんの名前とイメージに置き換えてください
image: username/repo:tag
deploy:
replicas: 5
restart_policy:
condition: on-failure
resources:
limits:
cpus: "0.1"
memory: 50M
ports:
- "80:80"
networks:
- webnet
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
networks:
- webnet
redis:
image: redis
ports:
- "6379:6379"
volumes:
- ./data:/data
deploy:
placement:
constraints: [node.role == manager]
networks:
- webnet
networks:
webnet:
Redis は Docker ライブラリ内に公式イメージがあるため、 image 名にあたる部分は redis のみに省略できます。そのため、ここでは ユーザ名/リポジトリ名 を明示する必要はありません。Redis では予め Redis 用にホスト側のポート 6379 をコンテナに対して公開するよう指定済みです。そのため、この Compose ファイルでは、クラスタ上のどこかのホスト上でポートを公開するのを指定するだけです。そのため、 Redis Desktop Manager で Redis インスタンスを管理するには、実際にはノード上のいずれかの IP アドレスを指定するだけで構いません。
最も重要なのは、このスタックに redis をデプロイするにあたり、データの保存を指定している箇所が2つあります。
redisは常にマネージャ上で動作し、常に同じファイルシステムを使用するredisは Redis のデータ保管用に、ホスト側ファイルシステム上の外部ディレクトリを、コンテナ内から/dataとしてアクセスする
同時に、ここで Redis データを「実際に保存」するのは、ホスト側の物理ファイルシステム上です。この指定がなければ、Redis はコンテナのファイルシステム内にある /data へデータを保管しようとするため、データを取り出すことができず、コンテナの再デプロイを行えなくなってしまいます。
実際のデータ保管には2つのコンポーネントが関わります。
- Redis サービスを置く場所は、同一ホスト上を用いる制約を設けます
- 作成したボリュームには、コンテナは(ホスト上の)
./dataを(Redis コンテナ内では)/dataとしてアクセスします。コンテナが稼働後は、ホスト上に指定した./dataにファイルが保管され続けます。
これで Redis を使う新しいスタックをデプロイする準備が整いました。
- マネージャ上で
./dataディレクトリを作成
$ docker-machine ssh myvm1 "mkdir ./data"
docker-machine scpで新しいdocker-compose.ymlファイルをコピー
$ docker-machine scp docker-compose.yml myvm1:~
docker stack deployをもう一度実行
$ docker-machine ssh myvm1 "docker stack deploy -c docker-compose.yml getstartedlab"
- ノードいずれかのウェブページを確認し(例:
http://192.168.99.101)、来訪者カウンタの動作を確認します。ここで表示されるデータは Redis で保管されたものです。
(Todo;図、ブラウザで Redis 対応 Hello World を確認)
また、他のノードの IP アドレスでポート 8080 を開き、ビジュアライザを確認します。そうしますと、 web と visualizer サービスと同様に、 redis サービスが動いているのが分かります。
(ToDo;VirualizerでRedisを確認するスクリーンショット)
まとめ(オプション)¶
このページで扱ったターミナルの録画 がこちらです。
以上、スタックとは内部で連携するサービスがすべて協調動作するものと学びました。皆さんは既にチュートリアルの Part 3 からスタックを使っていたのです。つまり「すごーい!」 スタック上へのサービス追加とは Compose ファイルへの追加と学んでいます。そして、どこで動かすのかという制約(constraint)と、作成したデータを保存し続ける場所としてのボリュームについて学びました。ですから、コンテナが停止して再デプロイしたとしても、アプリのデータは残り続けるのです。