Part 5:スタック

必要条件

  • Docker バージョン 1.13 以上のインストール

  • Part 4 を入手。

  • Part 1 の概要を読んでいること

  • Part 2 のコンテナの作成方法学んでいること

  • 自分で作成した friendlyhello イメージを レジストリに送信 して公開済みなのを確認します。ここでは、この共有イメージを使います。

  • イメージをコンテナとしてデプロイできるのを確認します。次のコマンドを実行しますが、 ユーザ名リポジトリタグ は皆さんのものに置き換えます。コマンドは dockerrun-p80:80ユーザ名/リポジトリ:タグ です。そして http://localhost/ を表示します。

  • Part 3 で扱った docker-compose.yml のコピーを持っていること

  • Part 4 でセットアップしたマシンが実行中かつ準備できていること。確認には docker-machinels を実行。マシンが停止している場合は、マネージャを docker-machinestartmyvm1 で起動し、ワーカを docker-machinestartmyvm2 で起動

  • Part 4 で作成した swarm (クラスタのこと)が実行中かつ準備できていること。確認には docker-machinesshmyvm1"dockernodels" を実行。swarm が起動中であれば、いずれのノードも status (状態)は ready (準備完了)。そうでなければ、swarm を再度初期化し、ワーカを swram としてセットアップ します。

はじめに

Part 4 では、 swarm のセットアップ方法を学びました。swarm とは Docker を実行しているマシンのクラスタであり、アプリケーションを複数のマシン上へ一斉にデプロイします。

この Part 5 では、 スタック(stack) という分散アプリケーション階層の頂上に辿り着きました。スタックは相互関係を持つサービスのグループであり、依存関係を共有します。そして、同時にオーケストレート(訳者注;複数のサーバ上で一斉に挙動する)やスケール(訳者注;サービスの拡大および縮小)します。1つのスタックでアプリケーション全体の能力を定義し、機能全体をコード化します(複雑なアプリケーションであれば、複数のスタックを使うことになるでしょう)

良いお知らせがあります。スタックに関する技術的な内容は Part 3 で既に学んだとおり、 Compose ファイルを作成し、 dockerstackdeploy を実行するだけです。しかし、これまで行ったことは1つのホスト上で1つのサービス・スタックを動かしただけであり、プロダクションではあまり見ない環境です。ここでは従来の学びに加え、複数のマシン上で複数の関連サービスをお互いに作成し、実行しましょう。

ここまでおつかれさまでした。あと一息です!

新しいサービスの追加と再デプロイ

サービスは docker-compose.yml に追加するだけであり、とても簡単です。まず、swarm でコンテナのスケジューリングを調べるために、自由に使える可視化サービスを追加しましょう。

  1. エディタで 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)とボリュームの詳細は後述します。

  1. 新しい docker-compose.yml を swarm マネージャ myvm1 にコピーします。

docker-machine scp docker-compose.yml myvm1:~
  1. マネージャ上で dockerstackdeploy コマンドを再度実行し、更新が必要なサービスはアップデートが始まります。

$ docker-machine ssh myvm1 "docker stack deploy -c docker-compose.yml getstartedlab"Updating service getstartedlab_web (id: angi1bf5e4to03qu9f93trnxm)Updating service getstartedlab_visualizer (id: l9mnwkeq2jiononb5ihz9u7a4)
  1. ビジュアライザを確認します。

Compose ファイルにあった visualizer はポート 8080 で動作します。 docker-machinels を実行して、実行中のノードの IP アドレス1つを確認します。いずれかの IP アドレスの1つのポート 8080 を開くと、ビジュアライザの動作を確認できます。

(スクリーンショット;todo)

期待した通り、マネージャ上では visualizer のコピーが動作し、 web の5つのインスタンスは swarm 全体に展開しています。図の内容が正しいかどうかを確認するには、 dockerstackps<stack> を実行します。

docker-machine ssh myvm1 "docker stack ps getstartedlab"

ビジュアライザはスタンドアローンのサービスのため、スタック上のあらゆるサービスと実行できます。また、その他のものと依存関係はありません。次は依存関係を 持つ サービスを作成しましょう。Redis サービスは来訪者カウンタ機能を提供します。

データの保持

同じワークフローを通して、今度はアプリのデータを保管する Redis データベースを追加しましょう。

  1. 末尾に 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 を使う新しいスタックをデプロイする準備が整いました。

  1. マネージャ上で ./data ディレクトリを作成

$ docker-machine ssh myvm1 "mkdir ./data"
  1. docker-machinescp で新しい docker-compose.yml ファイルをコピー

$ docker-machine scp docker-compose.yml myvm1:~
  1. dockerstackdeploy をもう一度実行

$ docker-machine ssh myvm1 "docker stack deploy -c docker-compose.yml getstartedlab"
  1. ノードいずれかのウェブページを確認し(例: http://192.168.99.101 )、来訪者カウンタの動作を確認します。ここで表示されるデータは Redis で保管されたものです。

(Todo;図、ブラウザで Redis 対応 Hello World を確認)

また、他のノードの IP アドレスでポート 8080 を開き、ビジュアライザを確認します。そうしますと、 webvisualizer サービスと同様に、 redis サービスが動いているのが分かります。

(ToDo;VirualizerでRedisを確認するスクリーンショット)

まとめ(オプション)

このページで扱ったターミナルの録画 がこちらです。

以上、スタックとは内部で連携するサービスがすべて協調動作するものと学びました。皆さんは既にチュートリアルの Part 3 からスタックを使っていたのです。つまり「すごーい!」 スタック上へのサービス追加とは Compose ファイルへの追加と学んでいます。そして、どこで動かすのかという制約(constraint)と、作成したデータを保存し続ける場所としてのボリュームについて学びました。ですから、コンテナが停止して再デプロイしたとしても、アプリのデータは残り続けるのです。