docker service create

読む時間の目安: 21 分

説明

新たなサービスを生成します。

API 1.24 以上  このコマンドを利用するには、クライアントとデーモンの API はともに、最低でも 1.24 である必要があります。 クライアント上においてdocker versionコマンドを実行して、クライアントとデーモンの API バージョンを確認してください。

Swarm このコマンドは Swarm オーケストレーターにおいて動作します。

利用方法

$ docker service create [オプション] IMAGE [COMMAND] [ARG...]

追加説明

指定されたパラメーターに従ってサービスを生成します。

メモ

これはクラスター管理コマンドです。 したがって Swarm 上のマネージャーノードにおいて実行する必要があります。 マネージャーノードやワーカーノードについては、Swarm モード を参照してください。

本コマンドの利用例については、以下に示す 利用例の節 を参照してください。

オプション

名前/省略形 デフォルト 説明
--cap-add API 1.41 以上
Linux ケーパビリティーを追加します。
--cap-drop API 1.41 以上
Linux ケーパビリティーを削除します。
--config API 1.30 以上
サービスに対して適用する設定を指定します。
--constraint 制約(constraint)を指定します。
--container-label コンテナーラベルを指定します。
--credential-spec API 1.29 以上
管理サービスアカウントに対する資格情報スペック(Credential spec)。(Windows のみ)
--detach , -d API 1.29 以上
サービスの終了を待たずに即座に戻ります。
--dns API 1.25 以上
カスタム DNS サーバーを設定します。
--dns-option API 1.25 以上
DNS オプションを設定します。
--dns-search API 1.25 以上
カスタム DNS 検索ドメインを設定します。
--endpoint-mode vip Endpoint モードを設定します。(vip または dnsrr)
--entrypoint イメージのデフォルト ENTRYPOINT をオーバーライドします。
--env , -e 環境変数を設定します。
--env-file 環境変数ファイルを読み込みます。
--generic-resource ユーザー定義リソースを設定します。
--group API 1.25 以上
コンテナーに対して必要な補助ユーザーグループを設定します。
--health-cmd API 1.25 以上
ヘルスチェックを実行するコマンド。
--health-interval API 1.25 以上
ヘルスチェックの実行間隔。(ms|s|m|h)
--health-retries API 1.25 以上
不健康(unhealthy)であると報告するのに必要な連続失敗回数。
--health-start-period API 1.29 以上
ヘルスチェックのリトライを数え始める前の、コンテナー初期化を行う開始時間。(ms|s|m|h)
--health-timeout API 1.25 以上
1 つのチェック処理実行に許容する最大時間。(ms|s|m|h) (デフォルトは 0s)
--host API 1.25 以上
1 つまたは複数のカスタムホスト-IP 間マッピングを設定します。(host:ip)
--hostname API 1.25 以上
コンテナーホスト名。
--init API 1.37 以上
各サービスコンテナー内部にて、シグナル送信と子プロセス管理を行う初期化処理を実行します。
--isolation API 1.35 以上
サービスの分離技術(isolation technology)モード。
--label , -l サービスラベル。
--limit-cpu CPU 数を制限します。
--limit-memory メモリ容量を制限します。
--limit-pids API 1.41 以上Swarm
プロセスの最大数を制限します(デフォルトは 0 = 無制限)。
--log-driver サービスにおけるログドライバー。
--log-opt ログドライバーオプション。
--max-concurrent API 1.41 以上
同時に実行するジョブタスク数(デフォルトは --replicas に等しい)。
--mode replicated サービスモード(replicated、global、replicated-job、global-job)。
--mount ファイルシステムマウントをサービスにアタッチします。
--name サービス名。
--network ネットワークアタッチ。
--no-healthcheck API 1.25 以上
コンテナー固有の HEALTHCHECK を無効にします。
--no-resolve-image API 1.30 以上
レジストリに対してイメージダイジェスト値や対応プラットフォームを確認しません。
--placement-pref API 1.28 以上
配置設定(placement preference)を追加します。
--publish , -p ノードのポートとしてポートを公開します。
--quiet , -q 経過出力を省略します。
--read-only API 1.28 以上
コンテナーのルートファイルシステムを読み取り専用としてマウントします。
--replicas タスク数。
--replicas-max-per-node API 1.40 以上
ノード当たりの最大タスク数。(デフォルトは 0、つまり無制限)
--reserve-cpu CPU の予約数。
--reserve-memory メモリの予約容量。
--restart-condition 条件を満たした際に再起動します。("none"|"on-failure"|"any") (デフォルトは "any")
--restart-delay 再起動実施の遅延時間(ns|us|ms|s|m|h)。
--restart-max-attempts 再起動の最大リトライ回数。
--restart-window 再起動ポリシーの評価に利用されるウィンドウ(ns|us|ms|s|m|h)。
--rollback-delay API 1.28 以上
タスクロールバック時の遅延時間(ns|us|ms|s|m|h)。(デフォルトは 0s)
--rollback-failure-action API 1.28 以上
ロールバック失敗時の処理(「pause」|「continue」)。(デフォルトは「pause」)
--rollback-max-failure-ratio API 1.28 以上
ロールバック時に許容される失敗率(デフォルトは 0)。
--rollback-monitor API 1.28 以上
各タスクのロールバックが失敗しないかを監視する時間間隔(ns|us|ms|s|m|h)。(デフォルトは 5s)
--rollback-order API 1.29 以上
ロールバック順。 (「start-first」|「stop-first」) (デフォルトは「stop-first」)
--rollback-parallelism 1 API 1.28 以上
同時にロールバックする最大タスク数(0 は全タスク同時)。
--secret API 1.25 以上
サービスに公開する Secret ファイル。
--stop-grace-period 強制的にコンテナーを kill する際の待機時間(ns|us|ms|s|m|h)。(デフォルトは 10s)
--stop-signal API 1.28 以上
コンテナーを停止するためのシグナル。
--sysctl API 1.40 以上
sysctl オプション。
--tty , -t API 1.25 以上
擬似 TTY を割り当てます。
--ulimit API 1.41 以上
ulimit オプション。
--update-delay 更新間の遅延時間(ns|us|ms|s|m|h)。(デフォルトは 0s)
--update-failure-action 更新失敗時のアクション(「pause」|「continue」|「rollback」)。(デフォルトは「pause」)
--update-max-failure-ratio API 1.25 以上
更新時に許容される失敗率。(デフォルトは 0)
--update-monitor API 1.25 以上
各タスクの更新が失敗しないかを監視する時間間隔(ns|us|ms|s|m|h)。(デフォルトは 5s)
--update-order API 1.29 以上
更新順(「start-first」|「stop-first」)。(デフォルトは「stop-first」)
--update-parallelism 1 同時に更新する最大タスク数(0 は全タスク同時)。
--user , -u ユーザー名または UID。(記述書式: <name|uid>[:<group|gid>])
--with-registry-auth レジストリ認証情報の詳細を Swarm エージェントに送信します。
--workdir , -w コンテナー内部のワーキングディレクトリ。

利用例

サービスの生成

$ docker service create --name redis redis:3.0.6

dmu1ept4cxcfe8k8lhtux3ro3

$ docker service create --mode global --name redis2 redis:3.0.6

a8q9dasaafudfs8q8w32udass

$ docker service ls

ID            NAME    MODE        REPLICAS  IMAGE
dmu1ept4cxcf  redis   replicated  1/1       redis:3.0.6
a8q9dasaafud  redis2  global      1/1       redis:3.0.6

プライベートリポジトリ上のイメージを利用したサービス生成

利用するイメージが、ログインを必要とするプライベートリポジトリ上にある場合は、ログインを済ませた後に、docker service create--with-registry-authフラグをつけて実行します。 プライベートリポジトリregistry.example.comにイメージがあるとすると、以下のようなコマンドを実行します。

$ docker login registry.example.com

$ docker service  create \
  --with-registry-auth \
  --name my_service \
  registry.example.com/acme/my_image:latest

このコマンド実行によってローカルクライアントにあるログイントークンが、サービスがデプロイされている Swarm ノードに送信されます。 その際には暗号化された WAL ログが利用されます。 この情報に基づいて各ノードからのレジストリへのログインが可能となり、イメージのプルが行われます。

レプリカタスク 5 を指定したサービス生成 (--replicas)

--replicasフラグを使って、複製化されているサービスに対してのレプリカタスク数を設定します。 以下のコマンドはレプリカタスク数5redisサービスを生成します。

$ docker service create --name redis --replicas=5 redis:3.0.6

4cdgfyky7ozwh3htjfw0d12qv

上のコマンドでは、サービスに対して 期待する タスク数を設定しています。 コマンドからの応答がすぐに返ってきても、実際にサービスがスケーリングするには多少の時間を要します。 REPLICAS欄には、サービスにおけるレプリカタスクの 実際の数期待する数 がともに示されます。

以下の例では、期待するレプリカ数が5と示されていますが、RUNNING(実行中)タスク数は3となっています。

$ docker service ls

ID            NAME   MODE        REPLICAS  IMAGE
4cdgfyky7ozw  redis  replicated  3/5       redis:3.0.7

すべてのタスクが生成され実行されると、実際のタスク数と期待されているタスク数が一致します。

$ docker service ls

ID            NAME   MODE        REPLICAS  IMAGE
4cdgfyky7ozw  redis  replicated  5/5       redis:3.0.7

Secret を使ったサービス生成

--secretフラグの指定により、コンテナーに対して Secret(機密情報)へのアクセスを許可します。

以下では Secret を指定してサービスを生成します。

$ docker service create --name redis --secret secret.json redis:3.0.6

4cdgfyky7ozwh3htjfw0d12qv

以下では Secret、ターゲット、ユーザーおよびグループ ID、モードを指定してサービスを生成します。

$ docker service create --name redis \
    --secret source=ssh-key,target=ssh \
    --secret source=app-key,target=app,uid=1000,gid=1001,mode=0400 \
    redis:3.0.6

4cdgfyky7ozwh3htjfw0d12qv

サービスから複数の Secret へのアクセスを許可するには、--secretフラグを複数指定します。

ターゲットの指定がない場合、Secret はコンテナー内の/run/secretsに置かれます。 ターゲット指定がなければ、Secret 名がコンテナー内のインメモリファイルとして用いられます。 ターゲットが指定されれば、それがファイル名として用いられます。 上のコマンド例においては、指定されている Secret ターゲットのそれぞれに対応して、/run/secrets/ssh/run/secrets/appという 2 つのファイルが生成されます。

Config を使ったサービス生成

--configフラグの指定により、コンテナーに対して Config(設定情報)へのアクセスを許可します

以下では Config を使ってサービスを生成します。 Config はredis-configにマウントされます。 その所有ユーザーはコンテナー内部においてこのコマンドを実行したユーザーです(たいていはrootです)。 そしてファイルモードを0444、つまり全読み込み可とします。 uidgidは、数値あるいは名称での指定ができます。 名称を利用する場合、指定するグループまたはユーザー名は、あらかじめコンテナー内において存在していなければなりません。 mod0755などのように、4 桁からなる数字で指定します。

$ docker service create --name=redis --config redis-conf redis:3.0.6

以下では Config を使ってサービスを生成し、ターゲットとファイルモードを指定します。

$ docker service create --name redis \
  --config source=redis-conf,target=/etc/redis/redis.conf,mode=0400 redis:3.0.6

サービスから複数の Config へのアクセスを許可するには、--configフラグを複数指定します。

ターゲットが指定されなかった場合、Config はコンテナー内の/に置かれます。 ターゲット指定がない場合、Config 名がコンテナー内のファイル名として用いられます。 ターゲット指定がある場合、それがファイル名に用いられます。

ローリングアップデートポリシーを使ったサービス生成

$ docker service create \
  --replicas 10 \
  --name redis \
  --update-delay 10s \
  --update-parallelism 2 \
  redis:3.0.6

この後に service update を実行すると、スケジューラーは一度に最大で 2 つのタスクのアップデートを行い、10s間隔でアップデートを行います。 詳しくは ローリングアップデートのチュートリアル を参照してください。

環境変数の設定(-e、--env)

これはサービス内のタスクすべてに対して環境変数を設定します。 たとえば以下のとおりです。

$ docker service create \
  --name redis_2 \
  --replicas 5 \
  --env MYVAR=foo \
  redis:3.0.6

サービスから複数の Config へのアクセスを許可するには、--configフラグを複数指定します。 複数の環境変数を指定するには、--envフラグを複数用いて、個々においてキーバリューのペアを指定します。

$ docker service create \
  --name redis_2 \
  --replicas 5 \
  --env MYVAR=foo \
  --env MYVAR2=bar \
  redis:3.0.6

ホスト名を指定したサービス生成 (--hostname)

このオプションはサービスコンテナーのホスト名に、指定文字列を設定します。 たとえば以下のとおりです。

$ docker service create --name redis --hostname myredis redis:3.0.6

サービスへのメタデータの設定(-l、--label)

ラベルはkey=valueペアであり、サービスに対してのメタデータとして適用されます。 サービスに 2 つのラベルをつけるには以下のようにします。

$ docker service create \
  --name redis_2 \
  --label com.example.foo="bar"
  --label bar=baz \
  redis:3.0.6

ラベルに関する詳細は カスタムメタデータの適用 を参照してください。

バインドマウント、ボリューム、メモリファイルシステムの追加

Docker では三種類のマウントをサポートします。 これを利用してコンテナーはファイルやディレクトリに対する読み書きを実現します。 ファイルやディレクトリは、ホストオペレーティングシステム上であっても、あるいはメモリ上のファイルシステムであってもかまいません。 その種類とは データボリューム(単にボリュームと呼ぶことがあります)、バインドマウントtmpfs であり、名前つきパイプ もあります。

バインドマウント は、このマウントを行ったコンテナーから、ホスト上のファイルやディレクトリを利用できるようにします。 バインドマウントは読み込み専用か読み書き可能かを選べます。 たとえばホスト上の/etc/resolv.confをバインドマウントすれば、ホストの DNS 情報を共有することができます。 あるいはコンテナーから、ホストの/var/log/myContainerLogsディレクトリに書き込むことができます。 バインドマウントの利用にあたって、ホストとコンテナーの間にパーミッションやアクセス制御などの詳細な部分に差異があったとすると、移植性の問題が発生する場合があります。

名前つきボリューム(named volume)は、コンテナー内において必要となる永続的なデータを、コンテナー生成に用いるイメージやホストマシンから切り離すためのメカニズムのことです。 名前つきボリュームは Docker によって生成され管理されます。 そこで名前つきボリュームは、コンテナーが利用されていない状態でも存続できます。 名前つきボリューム内のデータは、コンテナーとホストマシンとの間、複数コンテナー間でも共有が可能です。 Docker はボリュームの生成、管理、マウントを行うために ボリュームドライバー を利用します。 ボリュームは Docker コマンドを使って、バックアップや復元を行うことができます。

tmpfs マウントは、コンテナー内部において一時的なデータを利用するための tmpfs です。

npipe マウントは、ホストからコンテナーに向けて名前つきパイプをマウントします。

たとえば、軽量なウェブサーバーを起動させるイメージがあるとします。 これをベースイメージとして利用したり、ウェブサイトの HTML ファイルをコピーして別イメージにパッケージしたりすることも行うでしょう。 ウェブサイト内容が変更するたびに、新たなイメージとして更新することが必要となり、ウェブサイトを提供するコンテナーすべて再デプロイする必要に迫られます。 そんなやり方ではなく、ウェブサイト内容は名前つきボリューム内に保存するのが適切です。 そうすればウェブサーバーを構成するコンテナーの起動時に、その名前つきボリュームを割り当てて利用することができます。 ウェブサイトの更新時には、単に名前つきボリュームを更新するだけで済みます。

名前つきボリュームについての詳細は データボリューム を参照してください。

以下の表は、サービス内のバインドマウントまたは名前つきボリュームに適用されるオプションを説明するものです。

オプション 必須 内容説明
type

マウントのタイプを示します。volumebindtmpfsnpipe のいずれかです。type が指定されなかった場合のデフォルトは volume です。

  • volume管理ボリューム(managed volume)をコンテナーにマウントします。
  • bind は、ホスト上のディレクトリまたはファイルをコンテナーにバインドマウントします。
  • tmpfs はコンテナー内に tmpfs をマウントします。
  • npipe は、ホストからコンテナーに向けて名前つきパイプをマウントします(Windows コンテナーのみ)。
src または source type=bind または type=npipe の場合
  • type=volume: src という記述によりボリューム名を指定することもできます(たとえば src=my-volume)。 名前つきボリュームが存在しなかった場合は自動的に生成されます。 src が指定されなかった場合、ボリュームに対してランダムな名前が割り当てられます。 この名前はホスト上において必ずユニークなものとなります。 ただしクラスター内においてはユニークにならないことがあります。 ランダムに命名されたボリュームは、コンテナーと同一ライフサイクルとなります。 つまり container が削除される(service update の実行時や、サービスのスケール変更あるいは再配置時)と同時に削除されます。
  • type=bind: src は必須であり、バインドマウントするファイルまたはディレクトリへの絶対パスを指定します。(たとえば src=/path/on/host/)ファイルやディレクトリが存在しなかった場合にはエラーが発生します。
  • type=tmpfs: src はサポートされません。

dst または destination または target

必須

コンテナー内のマウントパス。たとえば /some/path/in/container/。 コンテナーのファイルシステム内にそのパスが存在しなかった場合、Engine がその指定に従ってディレクトリを生成し、その後にボリュームやバインドマウントがマウントされます。

readonly または ro

マウントの際に readonly オプションが指定されていなければ、Engine は read-write としてバインドマウントまたはボリュームをマウントします。 なお現状の Linux 実装においては readonly によりバインドマウントを行っても、そのサブマウントまでは readonly になりません。

  • true または 1 または値なしの場合、バインドマウントまたはボリュームをread-only としてマウントします。
  • false または 0 は、バインドマウントまたはボリュームを read-write としてマウントします。

バインドマウントのオプション

以下のオプションはバインドマウント(type=bind)の場合にのみ利用可能です。

オプション 内容説明
bind-propagation

バインドプロパゲーション の節を参照してください。

consistency

マウントにおける一貫性の要求状況。以下のいずれかです。

  • defaultconsistent と同じです。
  • consistent は完全な一貫性を表します。コンテナーランタイムとホストは、いかなる時点においても同一のマウント参照を維持します。
  • cached は、ホストから見たマウントの信頼性を維持します。ホスト上において発生した更新は、コンテナー内で参照できるようになるまでに時間を要します。
  • delegated は、コンテナーランタイムから見たマウントの信頼性を維持します。コンテナー上において発生した更新は、ホスト内で参照できるようになるまでに時間を要します。
bind-nonrecursive デフォルトにおいてサブマウントも、再帰的にバインドマウントされます。しかしこの動作は、readonly を使ってバインドマウントが行われた際には混乱の元となります。その場合のサブマウントは read-only にならないからです。 bind-nonrecursive を設定すれば、再帰的なバインドマウントを無効にできます。

設定値は以下のとおりです。

  • true または 1 は、再帰的なバインドマウントを無効にします。
  • false または 0、また設定がない場合にはこれがデフォルトになりますが、再帰的なバインドマウントを有効にします。
バインドプロパゲーション

バインドプロパゲーションとは、指定されたバインドマウントや名前つきボリュームによって生成されるマウントが、そのレプリカに対して情報伝達(propagate)をするかどうかを表わします。 ここで/mntというマウントポイントを考えます。 これが/tmpにマウントされているとします。 これに対するプロパゲーションの設定は、/tmp/a上のマウントが/mnt/aとして利用可能かどうかを制御するものです。 プロパゲーションの各設定においては、再帰的に対応するマウントポイントが存在します。 再帰的という点でいうと、仮に/tmp/a/fooとしてマウントされていたとします。 このときプロパゲーション設定は/mnt/a/tmp/aが存在するかどうかを定めるものです。

オプションbind-propagationは、バインドマウントとボリュームマウントのいずれにおいても、デフォルトはrprivateと設定されていますが、変更可能であるのはバインドマウントにおいてのみです。 つまり名前つきボリュームではバインドプロパゲーションはサポートされていません。

  • shared= マウント元に対するサブマウントは、マウント先にも公開されます。 マウント先に対するサブマウントも、マウント元に対して公開されます。
  • slave= shared マウントに類似。 ただし一方向のみ。 マウント元がサブマウントを公開するなら、マウント先でもこれを見ることができますが、マウント先がサブマウントを公開しても、マウント元からは見ることができません。
  • private= マウントはプライベートなものになります。 マウント元におけるサブマウントは、マウント先に公開されません。 またマウント先のサブマウントも、マウント元には公開されません。
  • rshared= shared と同様。 ただしプロパゲーションは、元々のマウントポイントまたはレプリカマウントポイントにネストされたマウントポイントとの間にも伝達されます。
  • rslave= slave と同様。 slave と同じく、プロパゲーションは、元々のマウントポイントまたはレプリカマウントポイントにネストされたマウントポイントとの間にも情報伝達されます。
  • rprivate= デフォルト。 privateと同様。 つまり元々のマウントポイントまたはレプリカマウントポイント内のサブマウントは、どの方向にも情報伝達されません。

バインドプロパゲーションの詳細については Linux カーネルの shared subtree に関するドキュメント を参照してください。

名前つきボリュームのオプション

以下のオプションは名前つきボリューム(type=volume)の場合にのみ利用可能です。

オプション 内容説明
volume-driver

ボリュームに対して利用するボリュームドライバープラグイン名。 デフォルトは "local"。 これが指定されている場合、ボリュームが存在しない場合にこのローカルボリュームドライバーを使ってボリュームが生成されます。

volume-label ボリュームの生成時に適用される 1 つまたは複数のカスタムメタデータ("labels")。 たとえば volume-label=mylabel=hello-world,my-other-label=hello-mars など。 ラベルに関する詳細は カスタムメタデータの適用 を参照してください。
volume-nocopy 空のボリュームをコンテナーに割り当てた際に、コンテナー内のマウントパス(dst)にすでにファイルやディレクトリが存在していた場合は、デフォルトで Engine がそのファイルやディレクトリをボリューム内にコピーし、ホストからのアクセスを可能とします。 この volume-nocopy を設定すると、コンテナー内のファイルシステムからボリュームへのファイルコピーが無効化され、空のボリュームがマウントされます。

設定値は以下のとおりです。

  • true または 1、また設定がない場合にはこれがデフォルトになりますが、コピーを無効にします。
  • false または 0 はコピーを有効にします。
volume-opt 指定するボリュームドライバーに固有のオプション。 このオプションはボリューム生成時にドライバーに受け渡されます。 オプションはキーバリューのペアをカンマで区切ったリストとして指定します。 たとえば volume-opt=some-option=some-value,volume-opt=some-other-option=some-other-value です。 指定するドライバーにおいて利用可能なオプションについては、各ドライバーのドキュメントを参照してください。

tmpfs のオプション

以下のオプションは tmpfs マウント(type=tmpfs)の場合にのみ利用可能です。

オプション 内容説明
tmpfs-size tmpfs マウントの容量をバイト単位で指定します。Linux におけるデフォルトは無制限です。
tmpfs-mode 8 進数表記による tmpfs のファイルモード。(たとえば "700""0700" など。) Linux におけるデフォルトは "1777"

「--mount」と「--volume」の違い

--mountフラグは、docker runにおける-vまたは--volumeフラグと、ほとんど同じオプションがサポートされています。 ただし以下のように重要な違いがあります。

  • --mountフラグではボリュームドライバーの指定が可能であり、各ボリュームごとに ボリュームドライバーオプションの指定ができます。 これはボリュームを生成しなくてもできることです。 それに比べてdocker runでは、--volume-driverフラグを使って、全ボリュームに共通するボリュームドライバーを指定します。

  • --mountフラグでは、ボリュームに対してカスタムメタデータ(「labels」)を指定することができます。 これはボリューム生成前に設定されます。

  • type=bind指定とともに--mountフラグを用いる場合、ホストパスはホスト上に 存在している パスでなければなりません。 パスは自動的に生成されないため、パスが存在していないとサービスはエラー終了します。

  • --mountフラグでは、Zフラグまたはzフラグを使ったボリュームのラベル変更はできません。 それらのフラグはselinuxのラベルづけに利用されています。

名前つきボリュームを用いたサービス生成

以下の例は、名前つきボリュームを利用するサービスを生成します。

$ docker service create \
  --name my-service \
  --replicas 3 \
  --mount type=volume,source=my-volume,destination=/path/in/container,volume-label="color=red",volume-label="shape=round" \
  nginx:alpine

サービスの各レプリカにおいては、タスクがデプロイされた場所のデフォルト(「local」)ボリュームドライバーから、Engine が「my-volume」という名のボリュームを要求します。 ボリュームが存在しなかった場合、Engine は新たなボリュームを生成して、そのラベルとして「color」と「shape」を設定します。

タスクが起動すると、ボリュームはコンテナー内の/path/in/container/にマウントされます。

注意する点として、デフォルトの(「local」)ボリュームドライバーのスコープは、あくまでローカルであるということです。 これはつまり、タスクがどこにデプロイされているかに依存します。 「my-volume」という名前のボリュームを 新たに 生成するか、同一サービス内の別タスクとの間で同じ「my-volume」を共有するかは状況次第です。 複数のコンテナーが 1 つの共有ボリュームに書き込みを行うとすると、コンテナー上で動作するソフトウェアが同一箇所への書き込みを並行処理するように設計されていないと、データ破壊を引き起こす可能性があります。 さらにコンテナーというものは Swarm オーケストレーターによって再スケジュールされ、別のノードに再配置されることがあるので、このことにも留意する必要があります。

匿名ボリュームを使ったサービス生成

以下の例では 3 つのレプリカを持つサービスを生成し、/path/in/containerにマウントされた匿名ボリュームを利用します。

$ docker service create \
  --name my-service \
  --replicas 3 \
  --mount type=volume,destination=/path/in/container \
  nginx:alpine

上のコマンドにおいては、ボリュームに対する名前(source)が指定されていないため、新たなボリュームが各タスクにて生成されます。 これは各タスクがそれぞれ独自のボリュームを確実に持つものとなるため、タスク間においてボリュームの共有は行われません。 匿名ボリュームは、これを利用するタスクが終了すると削除されます。

ホストのディレクトリにバインドマウントされたサービスの生成

以下の例は、サービスを起動するコンテナーにおいて、ホストのディレクトリ/path/in/containerをバインドマウントするものです。

$ docker service create \
  --name my-service \
  --mount type=bind,source=/path/on/host,destination=/path/in/container \
  nginx:alpine

サービスモードの設定(--mode)

サービスモードは、サービスが レプリカされた(replicated)ものか グローバルな ものかを決定します。 レプリカされたサービスは、指定に従って複数のタスクとして実行されます。 一方グローバルなサービスは、Swarm 内においてアクティブな各ノード上で実行されます。

以下のコマンドはグローバルサービスを生成します。

$ docker service create \
 --name redis_2 \
 --mode global \
 redis:3.0.6

サービス制約の指定(--constraint)

スケジューリングされるタスクに対しては制約表現(constraint expressions)を定義することができ、これにより一連のノードへの制限を課すことができます。 制約表現は 合致する==)か、あるいは 除外する!=)というルールにより表現されます。 制約が複数ある場合は、すべての表現に合致する(AND 条件による)ノードに適用されます。 制約は以下のように、ノードまたは Docker Engine ラベルに適用されます。

ノード属性 該当項目
node.id ノード ID node.id==2ivku8v2gvtg4
node.hostname ノードホスト名 node.hostname!=node-2
node.role ノードのロール(manager/worker node.role==manager
node.platform.os ノードのオペレーティングシステム node.platform.os==windows
node.platform.arch ノードのアーキテクチャー node.platform.arch==x86_64
node.labels ユーザー定義のノードラベル node.labels.security==high
engine.labels Docker Engine のラベル engine.labels.operatingsystem==ubuntu-14.04

engine.labelsは、オペレーティングシステムやドライバーなどのような Docker Engine ラベルに適用されます。 Swarm 管理者は操作をしやすくする目的で、docker node update コマンドを使ってnode.labelsを追加します。

たとえば以下の例では、redis サービスのタスクへの制約を設定するものであり、ノードのタイプラベルが queue であるものを対象とします。

$ docker service create \
  --name redis_2 \
  --constraint node.platform.os==linux \
  --constraint node.labels.type==queue \
  redis:3.0.6

サービスへの制約がクラスター内のどのノードにも合致しなかった場合、対象となるノードが見つからなかったというメッセージが出力されます。 ただし対象となるノードが出現した場合には、スケジューラーが調整ループを起動させてサービスをデプロイします。

以下の例では、制約を満たすノードが見つからなかったために、サービスが意図する状態にならなかったことを表しています。

$ docker service create \
  --name web \
  --constraint node.labels.region==east \
  nginx:alpine

lx1wrhhpmbbu0wuk0ybws30bc
overall progress: 0 out of 1 tasks
1/1: no suitable node (scheduling constraints not satisfied on 5 nodes)

$ docker service ls
ID                  NAME     MODE         REPLICAS   IMAGE               PORTS
b6lww17hrr4e        web      replicated   0/1        nginx:alpine

この後にクラスター内の 1 つのノードに対してregion=eastというラベルを追加すると、サービス調整が始まり、期待される数だけのレプリカがデプロイされます。

$ docker node update --label-add region=east yswe2dm4c5fdgtsrli1e8ya5l
yswe2dm4c5fdgtsrli1e8ya5l

$ docker service ls
ID                  NAME     MODE         REPLICAS   IMAGE               PORTS
b6lww17hrr4e        web      replicated   1/1        nginx:alpine

サービスの配置設定の指定(--placement-pref)

さまざまなカテゴリーのノードに対して、タスクを均等に割り振るようにサービスを設定することができます。 1 つの例として有用になるのが、データセンターや利用可能なゾーンが複数にわたっていて、そこにバランスよくタスクを割り振る場合です。 以下の例はこれを示しています。

$ docker service create \
  --replicas 9 \
  --name redis_2 \
  --placement-pref spread=node.labels.datacenter \
  redis:3.0.6

ここでは--placement-prefspreadストラテジー(現時点においては唯一サポートされているストラテジー)を用いて、datacenterノードラベルを持つノードにわたって均等にタスクを広げて(spread して)います。 この例では、全ノードにおいてノードラベルdatacenterが与えられているものとしています。 もし Swarm 内のノードにおいて三種類のラベル値が存在していたとすると、各値が与えられているノードに 3 分の 1 ずつのタスクが割り振られることになります。 たとえ 1 つの値を持つノードの数が他よりも多くても、この割り振りは変わりません。 たとえばノードの状態が以下であるとします。

  • node.labels.datacenter=eastを持つノードが 3 つ。
  • node.labels.datacenter=southを持つノードが 2 つ。
  • node.labels.datacenter=westを持つノードが 1 つ。

上ではdatacenterラベルを持つノードへの spread を行っており、サービスには 9 個のレプリカを設定しています。 したがって各 datacenter へは 3 つのレプリカが配置されるはずです。 ところでラベル値eastを持つノードは 3 つでした。 したがってその各ノードへは、この値に対して割り振られる 3 つのレプリカの 1 つがそれぞれに割り振られます。 またラベル値southを持つノードは 2 つです。 この値に対して割り振られる 3 つのレプリカは、そのノード間で分配されます。 つまり 1 つのノードが 2 つのレプリカを受け持つこととなり、残る 1 つのノードがレプリカ 1 つだけを受け持ちます。 最後にラベル値westを持つノードでは、westに割り当てられる 3 つのレプリカすべてを 1 つのノードが持つことになります。

1 つのカテゴリー(たとえばnode.labels.datacenter=south)を持つノードが、制約やリソース制限によって本来受け持つべきタスクを扱えない場合、余ったタスクは、可能であれば別のノードに割り当てられることになります。

配置設定(placement preferences)においては、Engine ラベルとノードラベルの両方をサポートします。 上の例ではノードラベルを用いていましたが、この例ではnode.labels.datacenterとしてラベルを参照したからです。 Engine ラベルの値に基づいて spread を行うのであれば、--placement-pref spread=engine.labels.<labelname> とします。

サービスにおける配置設定は複数追加することができます。 これを行うと設定が階層化されます。 つまりタスクに対して 1 つのカテゴリーにより分配が行われ、さらに別のカテゴリーを通じて分配が行われるといった具合です。 1 つの例として有用になるのが、データセンター間において公正にタスクを割り振り、各データセンターでは設定するラックに対してタスクを分割する場合です。 配置設定を複数指定する場合は--placement-prefフラグを複数回指定します。 その場合は指定準が重要になります。 配置設定は、スケジュール決定が行われる際に指定順により適用されます。

以下の例は、配置設定を複数指定したサービスを起動します。 タスクは初めに各データセンターに割り振られ、次にラックに対して割り振られます(それぞれラベルによって示されています)。

$ docker service create \
  --replicas 9 \
  --name redis_2 \
  --placement-pref 'spread=node.labels.datacenter' \
  --placement-pref 'spread=node.labels.rack' \
  redis:3.0.6

docker service updateによってサービスを更新する際に--placement-pref-addを利用すると、既存の配置設定に新たな配置設定を追加することができます。 また--placement-pref-rmは、引数に合致する既存の配置設定を削除します。

サービスに対するメモリ要求と制約の指定(--reserve-memory、--limit-memory)

適正にサービスを実行するのに特定のメモリ容量を最低でも必要とする場合は--reserve-memoryを用います。 これを用いると、サービスがその分のメモリ量を確保できるノードにしかノード配分を行いません。 この基準を満たすノードが 1 つもなかった場合、タスクはスケジューリングされず、ペンディング状態のままとなります。

以下の例は、4 GB のメモリ容量を利用でき、しかも確保可能であるノードを選んでから、その上にサービス実行するようなスケジューリングが行われます。

$ docker service create --reserve-memory=4GB --name=too-big nginx:alpine

1 つのノードに対してメモリ容量の確保が複数求められる場合に、その合計がそのノードでの利用可能容量を超える場合は、マネージャーノードはコンテナーのスケジューリングを行いません。

タスクがスケジュールされ実行された後は、--reserve-memoryはメモリ利用を制限しません。 ノード上において、指定容量以上のメモリをタスクが利用しないようにするには--limit-memoryを用います。 以下の例では、タスクが利用できる容量を 4 GB に制限します。 この場合に、ノードがたとえば 2 GB しかメモリを持っていなくても、タスクはスケジューリングされます。 --limit-memoryは上限を制限するだけのものであるからです。

$ docker service create --limit-memory=4GB --name=too-big nginx:alpine

--reserve-memoryおよび--limit-memoryを利用するにあたって、ホスト上のメモリ容量を超えた指定が行われても、ホスト容量内に抑えるような動作保証はありません。 サービスはいくらでも生成可能であり、それが利用するメモリの総量は、いくらでも利用可能メモリを消費していきます。

利用可能なメモリが際限なく消費されてしまうこの状況は、ホスト上に動作する別の(コンテナー化アプリ以外の)ソフトウェアに対しても考慮することが必要です。 --reserve-memoryの値が--limit-memoryの値よりも大きいか等しい場合、十分なメモリを有していないホストへのサービスのスケジューリングは行われません。 --limit-memoryはサービスのメモリ使用量をその制限以内に収めます。 したがってサービスのすべてにおいてメモリ予約やメモリ制限を設けていれば、Docker サービスがホストのメモリを消費し尽くすことを抑えられます。 ただしサービス以外のコンテナーやアプリケーションが Docker ホスト上で直接実行されている場合は、メモリを浪費する可能性は残ります。

ただしこの方法には欠点があります。 メモリ予約をするということは、そのノードにおいて利用可能なメモリを的確に利用しないことにもつながりかねません。 たとえば今、あるサービスが通常は 100 MB のメモリを利用するものとして、負荷次第ではピーク時に 500 MB まで利用するものがあったとします。 このサービスのメモリ予約量を 500 MB とする(そのピーク時の 500 MB を確保する)ことは、つまりほとんどのタイミングにおいて 400 MB を利用することなく無駄使いすることになります。

そこでもっと手堅く柔軟な方法をとることができます。

  • 手堅い方法 = 500 MB を予約した上で上限を 500 MB とします。 ただしそもそもがサービスコンテナーを VM として利用することになるため、本来ならホストにおいて高密度にサービス処理が行われるはずなのに、その最大の利点を失うことになります。

  • 柔軟な方法 = サービスが 500 MB 以上を必要とすることがわかっていて、利用制限を 500 MB にしてしまうと破綻します。 「通常」時が 100 MB で「ピーク」時が 500 MB であるならば、その間の値を予約します。 ただしサービスが「ピーク」時にあるときには、別のサービスまたはコンテナー以外の処理はピークに達しないことが前提です。

採用すべき手法は、何よりもメモリ利用状況がどのようなものであるかによって変わります。 手法を定めるためには、通常時、ピーク時の状況を十分にテストすることが必要です。

Linux においては、指定するホスト上においてサービスによるメモリーフットプリント(memory footprint)総量を制限することもできます。 これはオペレーティングシステムのレベルにおいて、cgroupsかあるいはこれに相当するシステムツールを利用して行います。

ノードごとの最大レプリカ数の指定(--replicas-max-per-node)

--replicas-max-per-nodeフラグを使えば、ノード上において実行するレプリカの最大数を指定できます。 以下のコマンドは 2 つのレプリカからなる nginx サービスを生成しますが、各ノードには 1 つのレプリカしか割り振らないようにします。

これが有用となる例としては--placement-prefとの併用により、複数のデータセンター間においてタスクをバランスよく割り振ることが考えられます。 --replicas-max-per-nodeを設定することによって、1 つのデータセンターのメンテナンスや障害が発生しても、レプリカをそこに割り振らないようにできます。

以下の例はこれを実現するものです。

$ docker service create \
  --name nginx \
  --replicas 2 \
  --replicas-max-per-node 1 \
  --placement-pref 'spread=node.labels.datacenter' \
  nginx

既存ネットワークへのサービスの割り当て(--network)

Swarm 内においてはオーバーレイネットワークを使って、複数のサービスを接続することができます。

まずはマネージャーノード上において、docker network createコマンドを使ってオーバーレイネットワークを生成します。

$ docker network create --driver overlay my-network

etjpu59cykrptrgw0z0hk5snf

Swarm モード内にオーバーレイネットワークを生成した後は、すべてのマネージャーノードがネットワークにアクセスできるようになります。

サービスを生成する際には--networkフラグを使って、サービスをオーバーレイネットワークに接続します。

$ docker service create \
  --replicas 3 \
  --network my-network \
  --name my-web \
  nginx

716thylsndqma81j6kkkb5aus

Swarm においては、サービスを実行している各ノードに向けて my-network が拡散されます。

同一のネットワーク上にあるコンテナーであれば、サービス検出 機能を使って互いにアクセスすることができます。

--networkフラグにおいて長い文法を用いると、エイリアスやドライバーオプションをリストにより指定できます。 たとえば--network name=my-network,alias=web1,driver-opt=field1=value1とします。

Swarm 外部へのサービスポートの公開(-p、--publish)

サービスポートを公開するには--publishフラグを用います。 これにより Swarm の外部からサービスへのアクセスが可能になります。 --publishフラグでは、引数に関して 2 通りの文法があります。 短い文法では引数の位置に意味があり、公開ポートとターゲットポートをコロン(:)で区切って指定します。

$ docker service create --name my_web --replicas 3 --publish 8080:80 nginx

長い文法による指定もあり、この方がわかりやすく、また多くのオプションを指定できます。 推奨されているのは長い文法の利用です。 なお短い文法を使った場合には、サービスモードを指定することはできません。 上のコマンドと同一のことを、長い文法を使って実行したのが以下の例です。

$ docker service create --name my_web --replicas 3 --publish published=8080,target=80 nginx

オプションとして指定できるものは以下のとおりです。

オプション 短い文法 長い文法 内容説明
公開ポートとターゲットポート --publish 8080:80 --publish published=8080,target=80

コンテナー内のターゲット(target)ポートとノード内でそこにマッピングされるポート。 ここにはルーティングメッシュ(ingress)またはホストレベルのネットワークが用いられます。 これ以外のオプションも利用可能であり本表以降に示します。 キーバリュー形式の文法は説明的であり、これが推奨されます。

モード 短い文法では設定不可 --publish published=8080,target=80,mode=host

ポートをバインドする際に用いるモード。 ingress または host のいずれか。 デフォルトは ingress でありルーティングメッシュを利用します。

プロトコル --publish 8080:80/tcp --publish published=8080,target=80,protocol=tcp

利用プロトコル。 tcpudpsctp のいずれか。 デフォルトは tcp。 2 つのプロトコルにポートをバインドする場合は -p または --publish フラグを 2 つ指定します。

ingressモードを利用してサービスポートを公開する場合、Swarm のルーティングメッシュが機能するため、ノード上にサービスタスクが起動しているかどうかに関係なく、サービスから全ノードへのアクセスは公開ポートを通じて可能になります。 hostモードを利用する場合は、サービスが実行されているノードに対してのみポートがバインドされます。 また 1 つのノード上において指定されるポートのみが 1 度だけバインドされます。 公開モードは長い文法を使った場合にの設定可能です。 詳しくは Swarm モードにおけるルーティングメッシュの利用 を参照してください。

管理サービスアカウントに対する資格情報スペックの提供(Windows のみ)

このオプションは Windows コンテナーを利用するサービスに対してのみ利用可能です。 --credential-specオプションはfile://<filename>あるいはregistry://<value-name>という書式でなければなりません。

書式としてfile://<filename>を用いた場合、参照するファイルは Docker データディレクトリ配下のサブディレクトリCredentialSpecsに存在している必要があります。 データディレクトリはデフォルトではC:\ProgramData\Docker\です。 たとえばfile://spec.jsonと指定した場合、C:\ProgramData\Docker\CredentialSpecs\spec.jsonを読み込むことになります。

書式としてregistry://<value-name>を用いた場合、資格情報スペック(credential spec)はデーモンホストの Windows レジストリから読み込まれます。 指定するレジストリ値は、以下に存在していなければなりません。

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\Containers\CredentialSpecs

テンプレートを使ったサービスの生成

service createコマンドにおけるフラグの中には、テンプレートを利用できるものがあります。 その際には Go 言語の text/template パッケージによって提供される文法を利用します。

サポートされるフラグは以下です。

  • --hostname
  • --mount
  • --env

Go 言語テンプレートによる記述書式は以下のとおりです。

プレースホルダー 内容説明
.Service.ID サービス ID
.Service.Name サービス名
.Service.Labels サービスラベル
.Node.ID ノード ID
.Node.Hostname ノードのホスト名
.Task.ID タスク ID
.Task.Name タスク名
.Task.Slot タスクスロット

テンプレート例

以下の例では、コンテナーのサービス名、ノード ID、コンテナーが配置されるホスト名を、テンプレートにより指定してこのコンテナーを生成します。

$ docker service create \
    --name hosttempl \
    --hostname="{{.Node.Hostname}}-{{.Node.ID}}-{{.Service.Name}}"\
    busybox top

va8ew30grofhjoychbr6iot8c

$ docker service ps va8ew30grofhjoychbr6iot8c

ID            NAME         IMAGE                                                                                   NODE          DESIRED STATE  CURRENT STATE               ERROR  PORTS
wo41w8hg8qan  hosttempl.1  busybox:latest@sha256:29f5d56d12684887bdfa50dcd29fc31eea4aaf4ad3bec43daf19026a7ce69912  2e7a8a9c4da2  Running        Running about a minute ago

$ docker inspect --format="{{.Config.Hostname}}" 2e7a8a9c4da2-wo41w8hg8qanxwjwsg4kxpprj-hosttempl

x3ti0erg11rjpg64m75kej2mz-hosttempl

分離モードの設定 (Windows)

Windows ノードにスケジュールされたタスクは、このノード専用に設定されたデフォルトの分離モード(isolation mode)を使って実行されます。 特定の分離モードを指定するには--isolationフラグを利用します。

$ docker service create --name myservice --isolation=process microsoft/nanoserver

Windows 上の分離モードとしてサポートされるのは以下です。

  • default: タスクが実行されるノードに固有となるデフォルトモード。
  • process: プロセス分離モードを利用します(Windows サーバーのみ)。
  • hyperv: Hyper-V 分離モードを利用します。

ジェネリックリソースを利用するサービスの生成

--generic-resourceフラグを利用すると、タスクが到達できるノードの種類を限定することができます(ノードがそのジェネリックリソース(generic resources)を公開している場合)。

$ docker service create \
    --name cuda \
    --generic-resource "NVIDIA-GPU=2" \
    --generic-resource "SSD=1" \
    nvidia/cuda

ジョブとしての実行

デーモンといえば長時間実行されるものですが、これとは違ってジョブというものは、操作を完了したらその後に停止するように設計されている特別なサービスのことです。 ジョブに属しているタスクが正常終了する(戻り値 0 を返す)と、そのタスクは「Completed」(完了)とマークがつけられ、再度実行されることはありません。

ジョブは 2 つのモード、つまりreplicated-jobまたはglobal-jobを使って起動されます。

$ docker service create --name myjob \
                        --mode replicated-job \
                        bash "true"

上のコマンドは 1 つのタスクを実行します。 これはbashイメージを用いてコマンドtrueを実行し、戻り値 0 を返して終了します。

ジョブは極めて特殊なサービスであるため、通常のサービスに比べて以下のような注意点があります。

  • 更新設定やロールバック設定を行うオプションは、どれも無効になります。 ジョブそのものは更新可能ですが、ロールアウトやロールバックができないため、そのようなオプションは設定できません。
  • ジョブが「Complete」(完了)状態に達した後は再起動できません。 これはつまりジョブにおいて--restart-conditionanyに設定することはon-failureを設定することと同じになります。

ジョブはレプリカされた(replicated)モード、およびグローバルモードのいずれでも利用できます。

レプリカされたモード

レプリカされた(replicated)ジョブとは、レプリカされたサービスに似ています。 --replicasフラグでは、ジョブを実行したい繰り返し数を指定します。

レプリカされたジョブの各レプリカは、デフォルトでそれぞれ 1 回だけ実行されます。 同タイミングでレプリカを複数実行したい場合は、その数を--max-concurrentフラグに指定します。

$ docker service create --name mythrottledjob \
                        --mode replicated-job \
                        --replicas 10 \
                        --max-concurrent 2 \
                        bash "true"

上のコマンドでは合計で 10 個のタスクが実行されます。 ただしどのタイミングにおいても、同時に実行されるのは 2 つだけです。

グローバルジョブ

グローバルジョブはグローバルサービスに似ています。 配置制約(placement constraints)に合致するノード上において、タスクが 1 度だけ実行されます。 グローバルジョブは、global-jobモードによって表現されます。

なおグローバルジョブが生成された後に、新たにクラスターにノードが追加されると、このジョブに対応するタスクが起動される点に注意してください。 グローバルジョブは「done」(完了)という状態になることはありません。 ただし、ジョブの制約を満たすすべてのノードが、完了タスクを有する状態はありえます。

上位コマンド

コマンド 説明
docker service サービスを管理します。
コマンド 説明
docker service create 新たなサービスを生成します。
docker service inspect サービスの詳細情報を表示します。
docker service logs サービスまたはタスクのログを取得します。
docker service ls サービス一覧を表示します。
docker service ps 1 つまたは複数サービスのタスクを一覧表示します。
docker service rm 1 つまたは複数のサービスを削除します。
docker service rollback サービス設定に対しての変更を元に戻します。
docker service scale 1 つまたは複数のレプリカサービスをスケール変更します。
docker service update サービスを更新します。