docker service create
読む時間の目安: 20 分
説明
新たなサービスを生成します。
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
フラグを使って、複製化されているサービスに対してのレプリカタスク数を設定します。
以下のコマンドはレプリカタスク数5
のredis
サービスを生成します。
$ 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
、つまり全読み込み可とします。
uid
とgid
は、数値あるいは名称での指定ができます。
名称を利用する場合、指定するグループまたはユーザー名は、あらかじめコンテナー内において存在していなければなりません。
mod
は0755
などのように、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 |
マウントのタイプを示します。volume、bind、tmpfs、npipe のいずれかです。type が指定されなかった場合のデフォルトは volume です。
|
|
src または source | type=bind または type=npipe の場合 |
|
dst または destination または target |
必須 |
コンテナー内のマウントパス。たとえば /some/path/in/container/。 コンテナーのファイルシステム内にそのパスが存在しなかった場合、Engine がその指定に従ってディレクトリを生成し、その後にボリュームやバインドマウントがマウントされます。 |
readonly または ro |
マウントの際に readonly オプションが指定されていなければ、Engine は read-write としてバインドマウントまたはボリュームをマウントします。 なお現状の Linux 実装においては readonly によりバインドマウントを行っても、そのサブマウントまでは readonly になりません。
|
バインドマウントのオプション
以下のオプションはバインドマウント(type=bind
)の場合にのみ利用可能です。
オプション | 内容説明 |
---|---|
bind-propagation |
バインドプロパゲーション の節を参照してください。 |
consistency |
マウントにおける一貫性の要求状況。以下のいずれかです。
|
bind-nonrecursive |
デフォルトにおいてサブマウントも、再帰的にバインドマウントされます。しかしこの動作は、readonly を使ってバインドマウントが行われた際には混乱の元となります。その場合のサブマウントは read-only にならないからです。
bind-nonrecursive を設定すれば、再帰的なバインドマウントを無効にできます。 設定値は以下のとおりです。
|
バインドプロパゲーション
バインドプロパゲーションとは、指定されたバインドマウントや名前つきボリュームによって生成されるマウントが、そのレプリカに対して情報伝達(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 を設定すると、コンテナー内のファイルシステムからボリュームへのファイルコピーが無効化され、空のボリュームがマウントされます。 設定値は以下のとおりです。
|
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-pref
にspread
ストラテジー(現時点においては唯一サポートされているストラテジー)を用いて、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 | 利用プロトコル。 tcp、udp、sctp のいずれか。 デフォルトは 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-condition
をany
に設定することは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 | サービスを更新します。 |