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)と、作成したデータを保存し続ける場所としてのボリュームについて学びました。ですから、コンテナが停止して再デプロイしたとしても、アプリのデータは残り続けるのです。