Part 3:サービス

必要条件

  • Part 1 の概要を読んでいること
  • Part 2 のコンテナの作成方法学んでいること
  • 自分で作成した friendlyhello イメージを レジストリに送信 して公開済みなのを確認します。ここでは、この共有イメージを使います。
  • イメージをコンテナとしてデプロイできるのを確認します。次のコマンドを実行しますが、 ユーザ名リポジトリ タグ は皆さんのものに置き換えます。コマンドは docker run -p 80:80 ユーザ名/リポジトリ:タグ です。そして http://localhost/ を表示します。

はじめに

Part 3では、アプリケーションをスケールアウトし、負荷分散(ロード・バランシング)を有効にします。そのためには、分散アプリケーション階層においてレベルを上げるする必要があります。すなわち、 サービス(service) にです。

  • サービス Services (今ここにいます)
  • コンテナ( part 2 で扱いました)

サービスとは

分散アプリケーションにおいて、アプリケーションにおける「サービス」と呼ばれる部分は異なる構成要素です。例えば、動画共有サイトをご想像ください。このサービスではアプリケーションのデータをデータベースに保管するでしょうし、ユーザが何かをアップロードしたらバックグラウンドでビデオ変換サービスが走るでしょうし、フロントエンド向けのサービス等もあるでしょう。

サービスとは、正に「本番環境におけるコンテナ」なのです。サービスは1つのイメージしか実行しません。しかし、イメージ実行にはコード化の手法を用います。例えば、何番のポートを使うか、サービスのキャパシティ(収容能力)に応じてコンテナの複製(レプリカ)を幾つ作成したらよいのか等です。サービスのスケール(規模)を変えるには、ソフトウェアのパーツとしての実行するコンテナ・インスタンス数の変更、すなわち、プロセス中のサービスに対して更に大きな計算資源を割り当てます。

幸運にも、Docker プラットフォームにおいては、サービスの定義、実行、スケールが非常に簡単です。これらを docker-compose.yml ファイルに書くだけです。

初めての docker-compose.yml ファイル

docker-compose.yml ファイルとは YAML ファイルであり、プロダクションにおける Docker コンテナのあるべき挙動を定義します。

docker-compose.yml

以下の内容を任意の場所に docker-commpose.yml として保存します。 Part 2 でレジストリに 送信したイメージ を確認し、 .yml``ファイルの ``username/repo:tag の部分を皆さんのイメージのものへ書き換えます。

version: "3"
services:
  web:
    # username/repo:tag を皆さんの名前とイメージに置き換えます
    image: username/repository:tag
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "80:80"
    networks:
      - webnet
networks:
  webnet:

この docker-compose.yml ファイルで Docker に以下の作業を伝えます:

  • Step 2 でアップロードしたイメージ をレジストリから取得
  • web という名前のサービスとして、イメージのインスタンスを5つ実行。それぞれのインスタンスには最大で CPU の 10% (全てのコアを横断して)かつメモリを 50MB に制限
  • コンテナが停止すると、直ちに再起動
  • ホスト側のポート 80 を、 web のポート 80 に割り当て
  • 『』web』』 のコンテナに対し、 webnet という名前の負荷分散ネットワークを経由してポート 80 を共有するよう命令(内部では、コンテナ自身の一時的なポートとして、 web のポート 80 を公開 )
  • デフォルトの設定として webnet ネットワークを定義(負荷分散されるオーバレイ・ネットワーク)

ヒント

Compose ファイルのバージョン、名前、コマンドの疑問について。 Compose ファイルに version: "3" とあるのにご注意ください。こちらは swarm mode 互換を意味します。これは deploy キー を使うためであり( Compose ファイル・フォーマット・バージョン 3.x 以上のみ対応)、サブオプションとして各サービスごと(例: web )の負荷分散とパフォーマンスを最適化します。ファイルを docker stack deploy コマンドで実行可能です(こちらもサポート対象は Compose ファイルがバージョン 3.x 以上のみ)。 swarm 設定のないバージョン3のファイルは docker-compose up でも実行可能ですが、これから構築する swarm のサンプルでは、stack を使ったデプロイにフォーカスします。

新しい負荷分散アプリケーションの実行

まず始めに、 docker stack deploy コマンドの実行が必要です。

docker swarm init

注釈

このコマンドの意味については Part 4 で扱います。もしも docker swarm init コマンドを実行しなければ、 「this node is not a swarm manager.」 (このノードは swarm マネージャではありません)とエラーが出ます。

次はコマンドを実行しましょう。アプリに名前を付ける必要があります。ここでは getstartedlab と指定します:

docker stack deploy -c docker-compose.yml getstartedlab

サービス・スタックでは、ホスト上にデプロイしたイメージを使った5つのコンテナインスタンスが実行中です。詳細を調べましょう。

アプリケーションのサービスが持つサービス ID を取得します。

docker service ls

Docker swarm(クラスタ)は作成したコンテナを、タスクとして実行します。タスクは状態(state)と各々が自身の ID を持ちます。

docker service ps <service>

注釈

Docker が swarm クラスタをサポートするにあたって、 SwarmKit と呼ばれるプロジェクトを構築に用いています。SwarmKit のタスクにコンテナは必須ではありませんが、Docker swarm のタスクにはコンテナの作成が定義されています。

それでは、タスクを調べ、コンテナ ID の出力を確認しましょう。

docker inspect --format='{{.Status.ContainerStatus.ContainerID}}' <task>

同様に、コンテナ ID を調べ、タスク ID を展開しましょう。

docker inspect --format="{{index .Config.Labels \"com.docker.swarm.task.id\"}}" <container>

ここでは5つのコンテナ全てを一覧表示します。

docker container ls -q

curl http://localhost コマンドを何度も実行するか、ブラウザで URL を何度か再読み込みします。そうしますと、アクセスごとにコンテナ ID の表示が変わり、負荷分散が動作しているのがわかります。つまり、5つのレプリカのうち1つが選ばれる、ラウンドロビン方式で応答します。

注釈

この段階では、コンテナが HTTP リクエストに応答するまで 30 秒ほどかかります。これは Docker や swarm の性能によるものではなく、Redis の依存関係による影響です。本件についてはチュートリアルの後半で扱います。

アプリのスケール

docker-compose.ymlreplicas 値の変更し、アプリをスケールできます。変更を保存したら、 docker stack deploy コマンドを再度実行します。

docker stack deploy -c docker-compose.yml getstartedlab

Docker は現状のまま更新を行いますので、スタックの停止やコンテナを停止する必要はありません。

次は docker container ls -q を再度実行しますと、指定したインスタンスのデプロイを確認できます。レプリカをスケールアップしていれば、より多くのタスクが起動しますので、より多くのコンテナが起動します。

アプリと swarm の解体(停止)

docker stack rm でアプリケーションを停止します。

docker stack rm getstartedlab

これはアプリケーションを削除(remove)しますが、1つの swarm ノードは起動および実行したままです( ocker node ls で表示します)。swarm (クラスタ)を停止するには docker swarm leave --force を実行します。

Docker はアプリケーションの起動だけでなくスケールも非常に簡単です。コンテナをプロダクションで動かす方法を学ぶのに、大きな前進です。次は、Docker マシンのクラスタ上で動作する swarm で、このアプリを動かす方法を学びましょう。

注釈

Docker では今回使ったような Compose ファイルでアプリケーションを定義します。そして、 Docker Cloud を用いたクラウド・プロバイダへのアップロードや、 Docker Enterprise エディション で任意のハードウェアやクラウド・プロバイダを利用できます。

まとめとチート・シート(オプション)

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

復習として docker run を実行するだけで、コンテナをプロダクションにおけるサービスとして正に実装されているのが分かるでしょう。コンテナの挙動をサービスとして Compose ファイルでコード化し、これを使ったアプリのスケール、制限、再デプロイに用いられます。サービスに対するする変更とは、変更箇所を書き換えての適用であり、サービスを起動するときと同じコマンド docker stack deploy を実行するだけです。

現時点における複数のコマンドを見てみましょう。

docker stack ls                                          # スタックやアプリ一覧
docker stack deploy -c <composefile> <appname>  # 特定の Compose ファイルを実行
docker service ls                          # アプリに関係ある実行中サービス一覧
docker service ps <service>                        # アプリに関係あるタスク一覧
docker inspect <task or container>                 # タスクまたはコンテナの調査
docker container ls -q                                     # コンテナ ID の一覧
docker stack rm <appname>                                # アプリケーションの解体

参考

Get Started, Part 3: Services | Docker Documentation
https://docs.docker.com/get-started/part3/