docker service create コマンドを使ってサービスをデプロイおよび管理する方法

DockerDockerBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、docker service create コマンドを使用して Docker Swarm 内でサービスをデプロイおよび管理する実践的な経験を積みます。高可用性とスケーラビリティのための単純なレプリケート型サービスや、すべてのノードで実行されるグローバルサービスなど、さまざまなタイプのサービスを作成して調査する方法を学びます。

さらに、シームレスなデプロイのためのローリングアップデートポリシーの実装、データの永続化と設定のためのバインドマウントと環境変数の利用、および Swarm 内でサービスタスクが実行される場所を制御するための配置制約と優先事項の適用など、高度なサービス構成を探索します。これらの手順を完了することで、Docker Swarm 環境でコンテナ化されたアプリケーションを効果的に管理する方法をしっかりと理解することができます。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/ImageOperationsGroup(["Image Operations"]) docker/ContainerOperationsGroup -.-> docker/run("Run a Container") docker/ContainerOperationsGroup -.-> docker/ls("List Containers") docker/ContainerOperationsGroup -.-> docker/ps("List Running Containers") docker/ContainerOperationsGroup -.-> docker/exec("Execute Command in Container") docker/ContainerOperationsGroup -.-> docker/inspect("Inspect Container") docker/ContainerOperationsGroup -.-> docker/create("Create Container") docker/ImageOperationsGroup -.-> docker/pull("Pull Image from Repository") subgraph Lab Skills docker/run -.-> lab-555224{{"docker service create コマンドを使ってサービスをデプロイおよび管理する方法"}} docker/ls -.-> lab-555224{{"docker service create コマンドを使ってサービスをデプロイおよび管理する方法"}} docker/ps -.-> lab-555224{{"docker service create コマンドを使ってサービスをデプロイおよび管理する方法"}} docker/exec -.-> lab-555224{{"docker service create コマンドを使ってサービスをデプロイおよび管理する方法"}} docker/inspect -.-> lab-555224{{"docker service create コマンドを使ってサービスをデプロイおよび管理する方法"}} docker/create -.-> lab-555224{{"docker service create コマンドを使ってサービスをデプロイおよび管理する方法"}} docker/pull -.-> lab-555224{{"docker service create コマンドを使ってサービスをデプロイおよび管理する方法"}} end

単純なレプリケート型サービスを作成する

このステップでは、Docker Swarm で単純なレプリケート型サービスを作成する方法を学びます。レプリケート型サービスとは、Swarm 全体で複数の同一タスクを実行するサービスです。これにより、高可用性とスケーラビリティが提供されます。

まず、Docker が実行中であり、正しいディレクトリにいることを確認しましょう。

docker version
pwd

Docker のバージョンと現在のディレクトリが /home/labex/project であることを示す出力が表示されるはずです。

サービスを作成する前に、必要な Docker イメージを取得する必要があります。この例では nginx イメージを使用します。

docker pull nginx:latest

このコマンドは、Docker Hub から nginx イメージの最新バージョンをダウンロードします。

では、3 つのレプリカを持つ my-nginx-service という名前の単純なレプリケート型サービスを作成しましょう。

docker service create --name my-nginx-service --replicas 3 nginx:latest

このコマンドは、nginx:latest イメージを使用して my-nginx-service という名前の新しいサービスを作成し、希望するレプリカ数を 3 に設定します。その後、Docker Swarm はこれらの 3 つのタスクを Swarm 内の利用可能なノードに分散させます。

サービスとそのタスクの状態を確認するには、docker service ls コマンドと docker service ps コマンドを使用できます。

docker service ls
docker service ps my-nginx-service

docker service ls コマンドは、Swarm で実行中のすべてのサービスを一覧表示し、それらの ID、名前、モード、レプリカ数、およびイメージを示します。docker service ps my-nginx-service コマンドは、my-nginx-service に関連付けられたタスクを表示し、それらの状態(例:Running、Shutdown)、希望する状態、および実行中のノードを含みます。「Running」状態のタスクが 3 つ表示されるはずです。

グローバルサービスを作成し、そのタスクを調査する

このステップでは、Docker Swarm でグローバルサービスを作成する方法を学びます。指定された数のタスクを実行するレプリケート型サービスとは異なり、グローバルサービスは、サービスの制約条件を満たす Swarm 内のすべてのノードで正確に 1 つのタスクを実行します。これは、すべてのノードで実行する必要がある監視エージェントやログ収集器などのサービスに役立ちます。

この例では busybox イメージを使用します。まず、イメージを取得しましょう。

docker pull busybox:latest

このコマンドは、busybox イメージの最新バージョンをダウンロードします。

では、my-global-service という名前のグローバルサービスを作成しましょう。

docker service create --name my-global-service --mode global busybox:latest sleep infinity

このコマンドは、busybox:latest イメージを使用して my-global-service という名前の新しいサービスを作成します。--mode global フラグは、これがグローバルサービスであることを指定します。sleep infinity コマンドは、コンテナを無期限に実行させるために使用されます。

グローバルサービスのタスクを調査するには、docker service ps コマンドを使用できます。

docker service ps my-global-service

このコマンドは、my-global-service に関連付けられたタスクを表示します。これはグローバルサービスであるため、Swarm 内の各ノードにつき 1 つのタスクが実行されているのが見えるはずです。この実験環境では、ノードが 1 つしかないため、おそらく 1 つのタスクしか表示されません。出力には、タスクの状態、希望する状態、および実行中のノードが表示されます。

また、docker service inspect コマンドを使用してサービスの構成を調査することもできます。

docker service inspect my-global-service

このコマンドは、サービスに関する詳細情報を提供します。これには、サービスのモード、レプリカ数(サービス一覧ではグローバルサービスの場合は 0 になりますが、docker service ps ではノードごとのタスクが表示されます)、およびその他の構成詳細が含まれます。

レプリカとローリングアップデートポリシーを持つサービスを作成する

このステップでは、レプリケート型サービスを作成し、そのローリングアップデートポリシーを設定する方法を学びます。ローリングアップデートを使用すると、タスクを新しいバージョンに徐々に置き換えることで、ダウンタイムなしでサービスを新しいバージョンに更新することができます。

引き続き nginx イメージを使用します。5 つのレプリカとローリングアップデートポリシーを持つ my-nginx-update-service という名前のレプリケート型サービスを作成しましょう。

docker service create \
  --name my-nginx-update-service \
  --replicas 5 \
  --update-delay 10s \
  --update-parallelism 2 \
  nginx:latest

このコマンドは、以下の構成でサービスを作成します。

  • --name my-nginx-update-service: サービス名を設定します。
  • --replicas 5: 希望するレプリカ数を 5 に設定します。
  • --update-delay 10s: 各タスクグループの更新間隔を 10 秒に設定します。
  • --update-parallelism 2: 同時に更新するタスク数を 2 に設定します。

これらの更新パラメータは、新しいバージョンのイメージをデプロイしたときにサービスがどのように更新されるかを定義します。Docker Swarm は一度に 2 つのタスクを更新し、次のバッチを更新する前に 10 秒待ちます。

docker service ls コマンドと docker service ps コマンドを使用して、サービスの状態とそのタスクを確認できます。

docker service ls
docker service ps my-nginx-update-service

my-nginx-update-service が 5/5 のレプリカで一覧表示され、タスクが「Running」状態であるのが見えるはずです。

では、イメージを別のバージョンに変更することでアップデートをシミュレートしましょう。nginx:1.21 イメージを使用します。まず、イメージを取得します。

docker pull nginx:1.21

次に、サービスを更新して nginx:1.21 イメージを使用するようにします。

docker service update --image nginx:1.21 my-nginx-update-service

このコマンドはローリングアップデートを開始します。Docker Swarm は、前に設定した --update-parallelism--update-delay の設定に従って、nginx:latest のタスクを nginx:1.21 のタスクに置き換え始めます。

docker service ps my-nginx-update-service を繰り返し実行することで、ローリングアップデートのプロセスを観察できます。

docker service ps my-nginx-update-service

古いイメージで「Running」状態のタスクが「Shutdown」状態に移行し、その後、新しいイメージで新しいタスクが開始されて「Running」状態に入るのが見えるでしょう。更新は 2 つのタスクごとに行われ、バッチ間には 10 秒の遅延があります。

バインドマウントと環境変数を使用したサービスを作成する

このステップでは、データを永続化するためにバインドマウントを使用し、コンテナ内のアプリケーションを構成するために環境変数を使用するサービスを作成する方法を学びます。バインドマウントを使用すると、ホストマシンのファイルまたはディレクトリをコンテナにマウントできるため、コンテナがデータにアクセスでき、コンテナが削除されてもデータは保持されます。環境変数は、アプリケーションに構成情報を渡す一般的な方法です。

まず、コンテナにバインドマウントするホストマシン上のディレクトリを作成しましょう。

mkdir -p ~/project/html

このコマンドは、~/project ディレクトリ内に html という名前のディレクトリを作成します。

次に、このディレクトリ内に簡単な HTML ファイルを作成しましょう。

echo "<h1>Hello from Bind Mount!</h1>" > ~/project/html/index.html

このコマンドは、~/project/html ディレクトリに index.html という名前のファイルを作成し、内容として "

Hello from Bind Mount!

" を書き込みます。

再び nginx イメージを使用します。1 つのレプリカを持ち、~/project/html ディレクトリをコンテナ内のデフォルトの Nginx ウェブルートディレクトリ (/usr/share/nginx/html) にバインドし、環境変数を設定する my-nginx-volume-service という名前のレプリケート型サービスを作成しましょう。

docker service create \
  --name my-nginx-volume-service \
  --replicas 1 \
  --publish published=8080,target=80 \
  --mount type=bind,source=/home/labex/project/html,target=/usr/share/nginx/html \
  --env MY_VARIABLE=hello \
  nginx:latest

新しいオプションを分解して説明します。

  • --publish published=8080,target=80: これは、ホストのポート 8080 をコンテナ内のポート 80 にマッピングします。これにより、ホストマシンから Nginx ウェブサーバーにアクセスできます。
  • --mount type=bind,source=/home/labex/project/html,target=/usr/share/nginx/html: これはバインドマウントを作成します。type=bind はマウントタイプを指定します。source=/home/labex/project/html はホストマシン上のパスです。target=/usr/share/nginx/html は、ホストディレクトリがマウントされるコンテナ内のパスです。
  • --env MY_VARIABLE=hello: これは、コンテナ内に MY_VARIABLE という名前の環境変数を hello という値で設定します。

サービスの状態とタスクを確認します。

docker service ls
docker service ps my-nginx-volume-service

タスクが「Running」状態になるまで待ちます。

これで、ウェブブラウザで http://localhost:8080 にアクセスするか、curl を使用して、コンテナ内で実行されている Nginx ウェブサーバーにアクセスできます。

curl http://localhost:8080

作成した index.html ファイルの内容 <h1>Hello from Bind Mount!</h1> が表示されるはずです。これにより、バインドマウントが正しく機能していることが確認できます。

環境変数を検証するには、実行中のコンテナ内でコマンドを実行できます。まず、実行中のサービスのタスク ID を見つけます。

docker service ps my-nginx-volume-service

出力からタスク ID をメモします。次に、docker exec を使用してコンテナ内でコマンドを実行します。<task_id> を実際のタスク ID に置き換えます。

docker exec < task_id > env | grep MY_VARIABLE

このコマンドは、タスク ID に関連付けられたコンテナ内で env コマンドを実行し、出力を grep MY_VARIABLE にパイプして環境変数を検索します。出力に MY_VARIABLE=hello が表示されるはずです。

配置制約と配置優先度を持つサービスを作成する

このステップでは、配置制約(placement constraints)と配置優先度(placement preferences)を使用して、Docker Swarm 内でサービスタスクをどこにデプロイするかを制御する方法を学びます。配置制約は、タスクをノードにスケジュールするためにノードが満たさなければならない厳格な要件です。配置優先度は、スケジューリングに影響を与える柔軟な要件であり、優先度を満たすノードがない場合でもタスクのスケジューリングを妨げません。

まず、現在のノードのラベルを確認しましょう。ラベルは、ノードにメタデータを付与するために関連付けることができるキーと値のペアです。

docker node inspect self --format '{{ .Spec.Labels }}'

このコマンドは、現在のノード(self で識別)を調査し、出力をフォーマットしてラベルを表示します。デフォルトでは、カスタムラベルは存在しない場合があります。

現在のノードにラベルを追加しましょう。node_type=app というラベルを追加します。

docker node update --label-add node_type=app self

このコマンドは、現在のノードを更新し、node_type=app というラベルを追加します。

次に、ラベルが追加されたことを確認しましょう。

docker node inspect self --format '{{ .Spec.Labels }}'

出力に map[node_type:app] が表示されるはずで、これはラベルが正常に追加されたことを示します。

では、ノードが node_type=app というラベルを持っていることを配置制約として要求する my-constrained-service という名前のレプリケート型サービスを作成しましょう。nginx イメージを使用します。

docker service create \
  --name my-constrained-service \
  --replicas 1 \
  --constraint 'node.labels.node_type == app' \
  nginx:latest

このコマンドは、制約を持つサービスを作成します。--constraint 'node.labels.node_type == app' は、このサービスのタスクは node_type ラベルが app と等しいノードにのみスケジュールできることを指定します。このラベルを現在のノードに追加したので、タスクはこのノードにスケジュールされるはずです。

サービスの状態とタスクを確認します。

docker service ls
docker service ps my-constrained-service

my-constrained-service が一覧表示され、そのタスクが現在のノードで実行されているのが見えるはずです。

次に、配置優先度を持つ別のサービスを作成しましょう。配置優先度は、スケジューラをガイドするために使用されますが、厳密に強制されるわけではありません。busybox イメージを使用し、node_type=database というラベルを持つノードを優先します。現在のノードにこのラベルがないため、タスクは依然として現在のノードにスケジュールされますが、そのラベルを持つ他のノードがあれば、スケジューラはそれらを優先します。

まず、busybox イメージを取得します。

docker pull busybox:latest

次に、配置優先度を持つサービスを作成します。

docker service create \
  --name my-preferred-service \
  --replicas 1 \
  --placement-pref 'spread=node.labels.node_type' \
  busybox:latest sleep infinity

--placement-pref 'spread=node.labels.node_type' オプションは、スケジューラに node_type ラベルの値に基づいてタスクをノード間で分散させるよう指示します。異なる node_type ラベルを持つマルチノードの Swarm では、これによりタスクがより均等に分散されます。この単一ノードの環境では、タスクは利用可能なノードに単純にスケジュールされます。

サービスの状態とタスクを確認します。

docker service ls
docker service ps my-preferred-service

my-preferred-service が一覧表示され、そのタスクが現在のノードで実行されているのが見えるはずです。

まとめ

この実験では、docker service create コマンドを使用して Docker Swarm でサービスをデプロイおよび管理する方法を学びました。まず、nginx イメージを使用して単純なレプリケート型サービスを作成し、高可用性とスケーラビリティのために必要なレプリカ数を指定しました。次に、docker service lsdocker service ps を使用して、サービスの状態を確認し、実行中のタスクを調査しました。

その後、グローバルサービスの作成を探索し、Swarm 内のすべての適格なノードで 1 つのタスクを実行するその動作を理解しました。これにより、Docker Swarm がさまざまな要件に基づいてサービスをデプロイする際の柔軟性が実証されました。