Docker run リファレンス¶
Docker は隔離(独立)したコンテナでプロセスを実行します。コンテナはホスト上で動くプロセスです。ホストとはローカルまたはリモートの環境です。作業者が docker run
を実行したら、コンテナのプロセスを隔離(独立)して実行します。コンテナは自身ファイルシステムとネットワークを持ち、ホスト上の他のプロセス・ツリーからは隔離されて(独立して)います。
このページではコンテナ実行時にリソースを指定できるよう、 docker run
コマンドの使い方の詳細を説明します。
一般的な形式¶
基本的な docker run
コマンドの形式は、次の通りです。
$ docker run [オプション] イメージ[:タグ|@ダイジェスト値] [コマンド] [引数...]
docker run
コマンドは、コンテナ形成の元になる イメージ 指定が必要です。イメージの開発者はイメージに関連するデフォルト値を定義できます。
- デタッチドあるいはフォアグラウンドで実行
- コンテナの識別
- ネットワーク設定
- 実行時の CPU とメモリの制限
- 権限と LXC 設定
docker run [オプション]
の実行時、作業者は設定の追加や、開発者がイメージに指定したデフォルト設定を上書き可能です。そして更に、作業者は Docker の実行時、ほぼ全てのデフォルト設定を上書きできます。 run コマンドは他の docker
コマンドより多くのオプションがあるため、作業者はイメージと Docker 実行時のデフォルト設定を上書きできます。
様々な種類の [オプション]
を理解するには、 オプションの種類 をご覧ください。
注釈
Docker システムの設定によっては、 docker run
コマンドを sudo
で実行する必要があるかもしれません。 docker
コマンドで sudo
を使わないようにするには、システム管理者に docker
という名称のグループの作成と、そこにユーザの追加を依頼してください。この設定に関するより詳しい情報は、各オペレーティング・システム向けのインストール用ドキュメントをご覧ください。
デタッチドまたはフォアグラウンド¶
Docker コンテナの起動時に、まず、コンテナをバックグラウンドで「デタッチド」モード(detached mode)で実行するか、デフォルトのフォアグラウンド・モード(foreground mode)で実行するかを決める必要があります。
-d=false: Detached mode: Run container in the background, print new container id
デタッチド (-d)¶
コンテナをデタッチド・モードで起動するには、 -d=true
か -d
オプションを使います。設計上、コンテナが実行するルート・プロセスが終了したら、デタッチド・モードで起動したコンテナも終了します。デタッチド・モードのコンテナは停止しても自動的に削除できません。つまり -d
オプションでは --rm
を指定できません。
デタッチドのコンテナでは service x start
コマンドを受け付けません。例えば、次のコマンドは nginx
サービスの起動を試みます。
$ docker run -d -p 80:80 my_image service nginx start
コンテナ内で nginx
サービスの起動は成功します。しかしながら、デタッチド・コンテナの枠組み内では処理に失敗します。これはルート・プロセス( service nginx start
)が終了するため、デタッチド・コンテナは停止されます。その結果、 nginx
サービスは実行しますが、実行を継続できません。この方法を使わず nginx
ウェブ・サーバのプロセスを実行するには、次のようにします。
$ docker run -d -p 80:80 my_image nginx -g 'daemon off;'
コンテナの入出力はネットワーク接続や共有ボリュームも扱えます。コマンドラインで docker run
を実行し終わった後でも、必要になる場合があるでしょう。
デタッチド・コンテナに再度アタッチ(接続)するには、 docker
attach コマンドを使います。
フォアグラウンド¶
フォアグラウンド・モード( -d
を指定しないデフォルト )の場合、 docker run
はコンテナの中でプロセスを開始し、プロセスの標準入出力・標準エラーをコンソールにアタッチします。これは TTY の振りをするだけでなく(TTY は大部分のコマンド・ラインで実行可能なものと想定しています)、シグナルも渡せます。
-a=[] : Attach to `STDIN`, `STDOUT` and/or `STDERR`
-t=false : Allocate a pseudo-tty
--sig-proxy=true: Proxify all received signal to the process (non-TTY mode only)
-i=false : Keep STDIN open even if not attached
Docker で -a
を指定しなければ、Docker は 自動的に全ての標準ストリームをアタッチ します。3つの標準ストリーム( STDIN
、 STDOUT
、 STDERR
)のうち、特定のものに対してのみ接続も可能です。
$ docker run -a stdin -a stdout -i -t ubuntu /bin/bash
(シェルのような)インタラクティブなプロセスでは、コンテナのプロセスに対して tty を割り当てるために、 -i -t
を一緒に使う必要があります。 後の例で出てきますが -i -t
は -it
と書けます。 クライアント側の標準出力を echo test | docker run -i busybox cat
のようにリダイレクトやパイプする場合 -t
は指定できません。
注釈
コンテナ内で PID 1 として実行しているプロセスは、Linux が特別に扱います。デフォルトの操作では、あらゆるシグナルを無視します。そのため、プロセスは SIGINT
か SIGTERM
で停止するようにコードを書かない限り、停止できません。
コンテナの識別¶
名前(–name)¶
作業者はコンテナを3つの方法で識別できます。
- 長い(ロング) UUID 識別子(”f78375b1c487e03c9438c729345e54db9d20cfa2ac1fc3494b6eb60872e74778”)
- 短い(ショート)UUID 識別子(”f78375b1c487”)
- 名前(”evil_ptolemy”)
UUID 識別子は Docker デーモンから与えられます。コンテナの名前を --name
オプションで割り当てなければ、デーモンはランダムな文字列から名前を生成します。コンテナに対する目的を表すには、 name
の定義が簡単でしょう。 name
を指定したら、これを Docker ネットワーク内でコンテナを参照用に使えます。この参照機能は、バックグラウンドでもフォアグラウンドどちらの Docker コンテナでも動作します。
注釈
デフォルトのブリッジ・ネットワーク内にあるコンテナの場合は、相互に名前で通信するにはリンクする必要があります。
PID 相当の機能¶
あとは、自動処理を簡単にするため、Docker は任意に選択したファイルに対してコンテナ ID を書き出せます。これは、プログラムがプロセス ID をファイルに書き出す(いわゆる PID ファイルです)のに似ています。
--cidfile="": コンテナの ID をファイルに書き出す
イメージ[@ダイジェスト値]¶
イメージ・形式 v2 以降のイメージを使えば、その中にダイジェスト値(digest)と呼ばれる識別子が、内容に対して割り当てられています。入力に使われたイメージファイルに対する変更が無ければ、ダイジェスト値とは予想されうる値であり、参照可能なものです。
次の例は sha256:9cacb71397b640eca97488cf08582ae4e4068513101088e9f96c9814bfda95e0
ダイジェスト値の alpine
イメージを使い、コンテナを実行する例です。
$ docker run alpine@sha256:9cacb71397b640eca97488cf08582ae4e4068513101088e9f96c9814bfda95e0 date
PID 設定(–pid)¶
--pid="" : コンテナに対する PID (プロセス)名前空間モードを指定
'container:<名前|id>': 他のコンテナの PID 名前空間に参加
'host': コンテナ内でホスト側の PID 名前空間を使う
デフォルトでは、全てのコンテナは有効な PID 名前空間を持っています。
PID 名前空間はプロセスの分離をもたらします。PID 名前空間はシステム・プロセスを見えないようにし、PID 1 を含むプロセス ID を再利用できるようにします。
コンテナがホスト上の特定のプロセス名前空間を共有する場合は、コンテナ内のプロセスが、システム上の全プロセスを基本的に見られるようにします。例えば、 strace
や gdb
のようなデバッグ用ツールを含むコンテナを構築した時、コンテナ内のデバッグ用プロセスのみツールを使えるように指定する場合です。
例:コンテナ内で htop を実行¶
Dockerfile を作成します:
FROM alpine:latest
RUN apk add --update htop && rm -rf /var/cache/apk/*
CMD ["htop"]
Dockerfile を構築し、イメージに myhtop
とタグ付け:
$ docker build -t myhtop .
次のコマンドを使いコンテナ内で htop
を実行:
$ docker run -it --rm --pid=host myhtop
他コンテナの pid 名前空間に参加するのは、コンテナのデバッグ用に便利です。
UTS 設定(–uts)¶
--uts="" : UTS 名前空間モードをコンテナに設定する
'host': コンテナ内でホストの UTS 名前空間を使用
UTS 名前空間とは、プロセスを実行する名前空間上で見えるホスト名とドメイン名を設定するものです。デフォルトでは、全てのコンテナは --uts=host
の指定により、自身の UTS 名前空間を持っています。 host
には、ホスト名として同じ UTS 名前空間をコンテナで使えるよう設定します。なお、 host
UTS モードでは --hostname
の指定ができないため、ご注意ください。
ホスト上と UTS 名前空間を共有したい場合もあるでしょう。例えば、コンテナを動かすホストがホスト名を変更してしまい、コンテナのホスト名も変更したい場合です。より高度な使い方としては、コンテナからホスト側のホスト名の変更を行うケースです。
IPC 設定(–ipc)¶
--ipc="" : コンテナに IPC モードを設定する
'container:<名前|id>': 他のコンテナの IPC 名前空間を再利用
'host': ホストの IPC 名前空間をコンテナの中で使用
デフォルトでは、全てのコンテナが有効な IPC 名前空間を持っています。
IPC (POSIX/SysV IPC) 名前空間は、共有メモリ・セグメント、セマフォ、メッセージ・キューと呼ばれる分離を提供します。
プロセス間通信は共有メモリ・セグメントはメモリの速度まで(ネットワーク・スタックをパイプするか通過するよりも速く加速)します。共有メモリとは、一般的にデータベースや、科学計算や緊急サービス産業向けの高性能アプリケーション向けカスタム・ビルド(典型的なのは、C/OpenMPI、C++ の高速化ライブラリ)に用いられます。この種のアプリケーションが複数のコンテナに分割される場合は、コンテナの IPC 機構を使って共有する必要があるでしょう。
ネットワーク設定¶
--dns=[] : コンテナ用のカスタム DNS サーバを設定
--net="bridge" : コンテナをネットワークに接続
'bridge': docker ブリッジ上でコンテナ用に新しいネットワーク・スタックを作成
'none': コンテナにネットワーク機能を付けない
'container:<name|id>': 他のコンテナ用ネットワーク・スタックを再利用
'host': コンテナ内でホスト側ネットワーク・スタックを使用
'NETWORK': 「docker network create」コマンドでユーザ作成したネットワークを使用
--net-alias=[] : コンテナにネットワーク内部用のエイリアスを追加
--add-host="" : /etc/hosts に行を追加(ホスト名:IPアドレス)
--mac-address="" : コンテナのイーサネット・デバイス Mac アドレスを指定
--ip="" : コンテナのイーサネット・デバイスに IPv4 アドレスを指定
--ip6="" : コンテナのイーサネット・デバイスに IPv6 アドレスを指定
デフォルトでは、全てのコンテナはネットワーク機能を持っており、外部に対する接続が可能です。作業者がネットワークを無効化したい場合は docker run --net=none
を指定し、内側と外側の両方のネットワーク機能を無効化します。このように指定したら、 I/O 処理はファイルに対してか、 STDIN
と STDOUT
のみになります。
公開用のポートを他のコンテナとリンクできるのは、デフォルト(ブリッジ)のみです。リンク機能はレガシー(過去の)機能です。リンク機能を使うよりも、常に Docker ネットワーク機能を使うべきです。
コンテナは、デフォルトではホストと同じ DNS サーバを使いますが、 --dns
で上書きできます。
デフォルトでは、コンテナに割り当てられる IP アドレスを使い、MAC アドレスを生成します。コンテナの MAC アドレスの指定は、 --mac-address
パラメータ(書式: 12:34:56:78:9a:bc
)を使い MAC アドレスを指定できます。 Docker は MAC アドレスがユニークかどうか(重複しているかどうか)を確認する仕組みが無いため、ご注意ください。
サポートしているネットワーク:
ネットワーク | 説明 |
---|---|
none | コンテナにネットワーク機能を持たせません。 |
bridge (デフォルト) | コンテナを各インターフェースに接続します。 |
host | コンテナ内でホスト側のネットワーク・スタックを使います。 |
container: <名前|id> | 他のコンテナ名か ID を指定し、そのネットワーク・スタックを使います。 |
NETWORK | ユーザが作成したネットワーク( docker network create コマンドを使用 )にコンテナを接続します。 |
ネットワーク:none¶
コンテナのネットワークを none
に指定したら、外部の経路に対してアクセス不能にします。コンテナ内では loopback
(ループバック)インターフェースが有効ですが、外部のトラフィックに対する経路が無くなります。
ネットワーク:bridge¶
コンテナのネットワークを bridge
に指定したら、コンテナは Docker のデフォルト・ネットワーク機能をセットアップします。ブリッジはホスト上で設定されるもので、通常は docker0
と名前が付けられます。そして、 veth
インターフェースのペアがコンテナ用に作成されます。 veth
ペアの片方はホスト側にアタッチされたままとなります。もう一方は、コンテナの名前空間の中で loopback
インターフェースに加えて追加します。ブリッジ・ネットワーク上で IP アドレスがコンテナに割り当てられ、コンテナに対するトラフィックはこのブリッジを経由します。
デフォルトでは、コンテナは各々の IP アドレスを経由して通信できます。コンテナ名で通信するには、リンクする必要があります。
ネットワーク:host¶
host
ネットワークをコンテナに設定したら、ホスト側のネットワーク・スタックと、全てのホスト上のインターフェースがコンテナ上でも共有できます。コンテナのホスト名はホストシステム上のホスト名と一致します。 host
ネットワーク・モードでは、 --mac-address
が無効になるのでご注意ください。 たとえ host
ネットワーク・モードだとしても、コンテナは自身の UTS 名前空間をデフォルトで持ちます。そのため、 host
ネットワーク・モードで --hostname
が許可されるのは、コンテナの中でホスト名を変えるだけです。 --hostname
同様、 --add-host
、 --dns
、 --dns-search
、 --dns-opt
オプションは host
ネットワーク・モードで利用可能です。これらのオプションはコンテナ内の /etc/hosts
や /etc/resolv.conf
を更新するだけです。ホスト側の /etc/hosts
や /etc/resolv.conf
は変更しません。
デフォルトの bridge
モードと比べ、 host
モードは 著しく ネットワーク性能が優れます。これは、bridge の場合は docker デーモンの仮想化レベルを通過しているのに対して、host の場合はネイティブなネットワーク・スタックを用いるからです。例えば、プロダクションのロードバランサや高性能のウェブサーバのような、ネットワーク性能がクリティカルな環境では、このモードでのコンテナ動作を推奨します。
注釈
--net="host"
の指定時は、コンテナは D-bus のようなローカル・システム・サービスに対してフルアクセス可能なため、安全ではないと考えられます。
ネットワーク:container¶
container
ネットワークをコンテナに指定したら、他のコンテナのネットワーク・スタックを共有します。他のコンテナ名は --net container:<名前|id>
の書式で指定する必要があります。 container
ネットワーク・モードでは、 --add-host
、 --hostname
、 --dns
、 --dns-search
、 --dns-opt
、 --mac-address
が無効になるだけでなく、 --publish
、 --publish-all
、 --expose
も無効になるのでご注意ください。
次の例は、Redis コンテナで Redis が localhost
をバインドしている時、 localhost
インターフェースを通して Redis サーバに redis-cli
コマンドを実行して接続します。
$ docker run -d --name redis example/redis --bind 127.0.0.1
$ # redis コンテナのネットワーク・スタックにある localhost にアクセスします
$ docker run --rm -it --net container:redis example/redis-cli -h 127.0.0.1
ユーザ定義ネットワーク¶
ネットワークを作成するには、Docker ネットワーク・ドライバか外部のネットワーク・ドライバ・プラグインを使います。同じネットワークに対して、複数のコンテナが接続できます。ユーザ定義ネットワークに接続したら、コンテナはコンテナの名前や IP アドレスを使い、簡単に通信できるようになります。
overlay
ネットワークやカスタム・プラグインは、複数のホストへの接続性をサポートしています。コンテナが同一のマルチホスト・ネットワークに接続していれば、別々のエンジンで起動していても、このネットワークを通して通信可能です。
以下の例は、内部 bridge
ネットワーク・ドライバを使ってネットワークを作成し、作成したネットワーク上でコンテナを実行します。
$ docker network create -d bridge my-net
$ docker run --net=my-net -itd --name=container3 busybox
/etc/hosts の管理¶
/etc/hosts
には localhost
や一般的な項目と同じように、自分が定義したコンテナのホスト名を追加できます。 /etc/hosts
に行を追加するには --add-host
フラグを使います。
$ docker run -it --add-host db-static:86.75.30.9 ubuntu cat /etc/hosts
172.17.0.22 09d03f76bf2c
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
86.75.30.9 db-static
コンテナがデフォルト・ブリッジ・ネットワークに接続し、他のコンテナと link
(リンク)すると、コンテナの /etc/hosts
ファイルが更新され、リンクされたコンテナ名が書き込まれます。
もしもコンテナがユーザ定義ネットワークに接続した場合は、コンテナの /etc/hosts
ファイルが更新され、ユーザ定義ネットワーク上の他のコンテナ名が書き込まれます。
注釈
Docker がコンテナの /etc/hosts
ファイルをリアルタイムに更新するかもしれません。そのため、コンテナ内のプロセスが /etc/hosts
ファイルを読み込もうとしても空だったり、あるいは最後まで読み込めなかったりする場合が有り得ます。ほとんどの場合、再度読み込みで問題が解決するでしょう。
再起動ポリシー(–restart)¶
Docker で実行時に --restart
フラグを使えば、再起動ポリシーを指定できます。再起動ポリシーとは、コンテナが終了時に再起動すべきかどうかを定義します。
コンテナの再起動ポリシーが有効な場合、 docker ps
でコンテナを見たら、常に Up
か Restarting
のどちらかです。また、再起動ポリシーが有効かどうかを確認するため、 docker events
を使うのも便利です。
Docker は以下の再起動ポリシーをサポートしています。
ポリシー | 結果 |
---|---|
no (なし) | コンテナが終了しても、自動的には再起動しません。これがデフォルトです。 |
on-failure [:最大リトライ数] | コンテナが 0 以外の終了コードで停止したら再起動します。オプションで Docker デーモンが何度再起動を試みるかを指定できます。 |
always (常に) | コンテナの終了コードに拘わらず、常にコンテナの再起動を試みます。Docker デーモンは無制限に再起動を試みます。また、デーモンの起動時にも、コンテナの状況に拘わらず常に起動を試みます。 |
unless-stopped (停止していない場合) | コンテナの終了コードに拘わらず、常にコンテナの再起動を試みます。しかし、直近のコンテナが停止状態であったのであれば、デーモンの起動時にコンテナを開始しません。 |
サーバが溢れかえるのを防ぐため、再起動の前に遅延時間が追加されます(遅延は100ミリ秒から開始し、直前の値の2倍になります)。つまり、デーモンは100ミリ秒待った後は、200ミリ秒、400、800、1600…と on-failure
上限に到達するか、あるいは、コンテナを docker stop
で停止するか、 docker rm -f
で強制削除するまで続けます。
コンテナの再起動が成功すると(コンテナは少なくとも10秒以内で起動します)、遅延時間の値は再び 100 ミリ秒にリセットされます。
on-failure ポリシーを使えば、Docker がコンテナの再起動を試みる最大回数を指定できます。デフォルトでは、Docker はコンテナを永久に再起動し続けます。コンテナの再起動(を試みる)回数は docker inspect
で確認可能です。例えば、コンテナ「my-container」の再起動数を取得するには、次のようにします。
$ docker inspect -f "{{ .RestartCount }}" my-container
# 2
あるいは、コンテナが(再)起動した時刻を知るには、次のようにします。
$ docker inspect -f "{{ .State.StartedAt }}" my-container
# 2015-03-04T23:47:07.691840179Z
再起動ポリシーと クリーンアップ は同時に指定できません。 --restart
と --rm
を同時に指定してもエラーになります。
例¶
$ docker run --restart=always redis
こちらの例は、 常に (always) 再起動するポリシーで redis
コンテナを実行します。そのため、コンテナが停止すると Docker はコンテナを再起動します。
$ docker run --restart=on-failure:10 redis
こちらの例は、 失敗したら (on-failure) 10回カウントするまで再起動を行うポリシーで redis
コンテナを起動しています。もし redis
コンテナが 0 以外の状態で終了したら、Docker はコンテナの再起動を10回続けて試みます。再起動の上限を設定できるのは、 on-failure ポリシーを有効にした場合のみです。
終了ステータス(exit status)¶
docker run
の終了コードから得られる情報は、なぜコンテナが実行に失敗したかや、なぜ終了したかです。 docker run
がゼロ以外のコードで終了する時、終了コードは chroot
標準に従います。
125 は Docker デーモン 自身 のエラー発生です。
$ docker run --foo busybox; echo $?
# 定義されていない --foo フラグを指定したため
See 'docker run --help'.
125
126 は コンテナ内のコマンド が実行できない場合のエラーです。
$ docker run busybox /etc; echo $?
# "/etc" には実行権限がありません
docker: Error response from daemon: Contained command could not be invoked
126
127 は コンテナ内のコマンド が見つからない場合です。
$ docker run busybox foo; echo $?
# 環境変数 $PATH の中に "foo" 実行ファイルが見つかりません。
docker: Error response from daemon: Contained command not found or does not exist
127
コンテナ内におけるコマンド の 終了コード は上書きできます。
$ docker run busybox /bin/sh -c 'exit 3'
# 3
クリーンアップ(–rm)¶
デフォルトではコンテナを終了しても、コンテナのファイルシステム(の内容)を保持し続けます。これにより、多くのデバッグをより簡単にします(最後の状態を確認できるため)。そして、全てのデータを維持し続けるのがデフォルトです。しかし、短い期間だけ フォアグラウンド で動かしたとしても、これらのコンテナのファイルシステムが溜まり続けます。そうではなく、 コンテナの終了時に、自動的にコンテナをクリーンアップし、ファイルシステムを削除する には --rm
フラグを追加します。
--rm=false: Automatically remove the container when it exits (incompatible with -d)
注釈
--rm
フラグを設定したら、コンテナの削除時、関連するボリュームも削除します。これは docker rm -v my-container
の実行と同じです。ただし、名前を指定しなかったボリュームのみ削除します。例えば docker run --rm -v /foo -v awesome:/bar busybox top
の場合、 /foo
ボリュームを削除します。しかし、 /bar
は削除されません。 --volume-form
で継承しているボリュームが削除されないのと同じ仕組みです。このように、オリジナルのボリュームに名前が指定されていれば、そこは削除 されません 。
セキュリティ設定¶
--security-opt="label=user:USER" : コンテナの user ラベルを指定
--security-opt="label=role:ROLE" : コンテナの role ラベルを指定
--security-opt="label=type:TYPE" : コンテナの type ラベルを指定
--security-opt="label=level:LEVEL" : コンテナの lovel ラベルを指定
--security-opt="label=disable" : コンテナのラベル割り当てを無効化
--security-opt="apparmor=PROFILE" : コンテナに適用する apparmor profile を指定
--security-opt="no-new-privileges" : コンテナが新しい権限を得るのを無効化
--security-opt="seccomp=unconfined": コンテナ用の seccomp 制限を無効化
--security-opt="seccomp=profile.json": sccomp フィルタで使うホワイトリスト syscall seccompo Json ファイルを指定
各コンテナに対するデフォルトのラベリング・スキーマ(labeling scheme)は --security-opt
フラグを指定することで上書き可能です。コンテナ間で同じ内容を共有できるようレベルを指定するには、次のようにコマンドを実行します。
$ docker run --security-opt label=level:s0:c100,c200 -i -t fedora bash
注釈
MLS ラベルの自動変換は、現在サポートしていません。
コンテナに対するセキュリティ・ラベリングを無効化するには、 --permissive
フラグを使い、次のように指定します。
$ docker run --security-opt label=disable -i -t fedora bash
コンテナ内のプロセスに対して、何らかのセキュリティ・ポリシーを適用するには、コンテナに対して何らかのタイプを指定します。コンテナを実行する時、Apache のポートのみがリッスンできるようにするには、次のように実行します。
$ docker run --security-opt label=type:svirt_apache_t -i -t centos bash
注釈
ここでは svirt_apache_t
タイプ に対する書き込みポリシーがあるものと想定しています。
コンテナのプロセスに特権を追加できないようにするには、次のコマンドを実行します。
$ docker run --security-opt no-new-privileges -it centos bash
より詳しい情報は、 カーネルのドキュメント をご覧ください。
カスタム cgroups の指定¶
--cgroup-parent
フラグを使うことで、コンテナを特定の cgroup で実行できるようにします。これにより自分自身で cgroup の作成や管理が可能になります。各 cgroup に対してカスタム・リソースを定義でき、コンテナを共通の親グループ下に置くこともできます。
実行時のリソース制限¶
作業者はコンテナのパフォーマンス・パラメータも調整できます。
オプション | 説明 |
---|---|
-m , --memory="" |
メモリの上限(書式: <数値> [<単位>] 、単位は b、k、m、g のいずれか) |
--memory-swap="" |
合計メモリの上限(メモリ+スワップ、書式: <数値> [<単位>] 、単位は b、k、m、g のいずれか) |
--memory-reservation="" |
メモリのソフト・リミット(書式: <数値> [<単位>] 、単位は b、k、m、g のいずれか) |
--kernel-memory="" |
カーネル・メモリの上限(書式: <数値> [<単位>] 、単位は b、k、m、g のいずれか) |
-c , --cpu-shares=0 |
CPU 共有(CPU shares)を相対値で指定 |
--cpu-period=0 |
CPU CFS (Completely Fair Scheduler) ピリオドの上限(訳者注:cgroup による CPU リソースへのアクセスを再割り当てする間隔) |
--cpuset-cpus="" |
実行する CPU の割り当て(0-3, 0,1) |
--cpuset-mems="" |
実行するメモリ・ノード(MEM)の割り当て(0-3, 0,1)。NUMA システムのみで動作 |
--cpu-quota=0 |
CPU CFS (Completely Fair Scheduler) のクォータを設定 |
--blkio-weight=0 |
ブロック I/O ウエイト(相対値)を 10 ~ 1000 までの値でウエイトを設定 |
--oom-kill-disable=false |
コンテナを OOM killer による停止を無効化するかどうか指定 |
--memory-swappiness="" |
コンテナがメモリのスワップ度合いを調整。整数値の 0 ~ 100 で指定 |
ユーザ・メモリの制限¶
ユーザのメモリ使用を制限するには、4つの方法があります。
オプション | 結果 |
---|---|
memory=inf, memory-swap=inf (デフォルト) | コンテナに対する上限を設けない。コンテナは必要な分のメモリを使える |
memory=L<inf, memory-swap=inf | (memory を指定し、memory-swap を -1 にする)コンテナは L バイト以上のメモリ使用が許されないが、必要があればスワップを使える(ホスト側がスワップ・メモリをサポートしている場合) |
memory=L<inf, memory-swap=2*L | (memory を指定するが memory-swap は指定しない)コンテナは L バイト以上のメモリ使用は許されないが、指定した値の2倍の「追加」スワップ・メモリが使える |
memory=L<inf, memory-swap=S<inf, L<=S | (memory も memory-swap も指定する)コンテナは L バイト以上のメモリ使用が許されないが、「追加」スワップ・メモリは S バイトまで使える |
例:
$ docker run -ti ubuntu:14.04 /bin/bash
メモリを設定していません。これはコンテナ内のプロセスは必要な分だけメモリが使えます。それだけでなく、スワップ・メモリも同様に必要なだけ使えます。
$ docker run -ti -m 300M --memory-swap -1 ubuntu:14.04 /bin/bash
メモリ上限を指定し、スワップ・メモリの制限を無効化しました。これはコンテナ内のプロセスは 300M のメモリを使えます。それだけでなく、スワップ・メモリは必要なだけ使えます(ホスト側がスワップ・メモリをサポートしている場合)。
$ docker run -ti -m 300M ubuntu:14.04 /bin/bash
メモリの上限のみ設定しました。これはコンテナが 300M のメモリと 300M のスワップ・メモリを使えます。合計の仮想メモリサイズ(total virtual memory size、 –memory-swap で指定)はメモリの2倍に設定されます。今回の例では、メモリ+スワップは 2×300M ですので、プロセスは 300M のスワップ・メモリを利用できます。
$ docker run -ti -m 300M --memory-swap 1G ubuntu:14.04 /bin/bash
メモリとスワップ・メモリを指定しましたので、コンテナ内のプロセスは 300M のメモリと 700M のスワップ・メモリを使えます。
メモリ予約(memory reservation)は、メモリに対するある種のソフト・リミットであり、共有メモリを大きくします。通常の状況下であれば、コンテナは必要とするだけ多くのメモリを使うことができます。そして、 -m
か --memory
オプションがある時のみ、コンテナに対してハード・リミットが設定されます。メモリ予約が設定したら、Docker はメモリのコンテンション(競合)や少ないメモリを検出し、コンテナが予約した上限まで使えるようにします。
メモリ予約の値は、常にハード・リミット以下に設定しなければ、ハード・リミットが先に処理されてしまいます。予約値を 0 に設定するのは、予約しないのと同じです。デフォルトでは(予約をセットしない場合)、メモリ予約とはメモリのハード・リミットと同じです。
メモリ予約とはソフト・リミット機能であり、制限を超過しないことを保証しません。その代わりに、かなりメモリが競合する場合、予約のヒント/設定に基づいてメモリの割り当てを試みる機能があります。
次の例はメモリの上限( -m
)を 500M に制限し、メモリ予約を 200M に設定します。
$ docker run -ti -m 500M --memory-reservation 200M ubuntu:14.04 /bin/bash
この設定の下では、コンテナはメモリを 200MB 以上 ~ 500MB 以下まで使えます。次のシステム・メモリはコンテナのメモリが 200MB 以下になるよう縮小を試みます。
次の例はメモリのハード・リミットを設定せず、メモリ予約を 1G に設定します。
$ docker run -ti --memory-reservation 1G ubuntu:14.04 /bin/bash
コンテナはメモリを必要なだけ使えます。メモリ予約設定により、コンテナが長時間多くのメモリを消費しなくなります。これはコンテナがメモリを消費したとしても、予約分を使えるようにメモリの使用を縮小しようとするからです。
デフォルトでは、アウト・オブ・メモリ(OOM; out of memory)エラーが発生したら、カーネルはコンテナ内のプロセスを停止(kill)します。この振る舞いを変更するには、 --oom-kill-disable
オプションを使います。また、 -m/--memory
オプションを指定した時のみ、コンテナに対する OOM が無効化できます。もし -m
フラグがセットされなければ、ホスト側でアウト・オブ・メモリ処理が発生します。また、ホスト側のシステム・プロセスが空きメモリを必要とするため、対象のプロセスを停止(kill)します。
次の例はメモリの上限を 100M とし、対象となるコンテナに対する OOM killer (アウト・オブ・メモリ処理による強制停止)を無効化します。
$ docker run -ti -m 100M --oom-kill-disable ubuntu:14.04 /bin/bash
次の例では、危険なフラグの使い方を説明します。
$ docker run -ti --oom-kill-disable ubuntu:14.04 /bin/bash
コンテナは無制限にメモリを使えるため、ホスト上のメモリを使い果たしたら、空きメモリ確保のために、システム・プロセスを停止する必要が出てきます。
カーネル・メモリ制限¶
カーネル・メモリはスワップ・アウトできないため、ユーザ・メモリとは根本的に異なります。このスワップができないことにより、システム・サービスがカーネル・メモリを多く使えないように妨害する可能性があります。カーネル・メモリとは、次の項目を指します。
- stack pages
- slab pages
- sockets memory pressure
- tcp memory pressure
これらのメモリを制限するため、カーネル・メモリの上限を設定できます。例えば、各プロセスが同じスタック・ページ(stack page)を使うようにする場合です。カーネル・メモリの制限により、カーネル・メモリの使用量が大きい時、新しいプロセスの作成を妨げます。
カーネル・メモリはユーザ・メモリとは完全に独立しています。その代わり、ユーザ・メモリを制限すると同時に、カーネル・メモリの制限も必要です。上限の設定には3つの方法があります。ここでは、「U」はユーザ・メモリの上限で、「K」はカーネルの上限とみなしています。
オプション | 結果 |
---|---|
U != 0, K = inf (デフォルト) | カーネル・メモリが使う前に、標準的なメモリ制限を設ける仕組み。カーネル・メモリは完全に無視される。 |
U != 0, K < U | カーネル・メモリをユーザ・メモリのサブセットとする。この設定は cgroup ごとに大きな合計メモリ容量をオーバーコミットで割り当て、デプロイする場合に使いやすい。カーネル・メモリ制限のオーバコミットは、全く推奨されていない。範囲が再利用できないメモリ領域の場合が有り得るため。この例では、 K を設定したので、全グループの合計は、全メモリ容量を超えられない。そして、システム・サービスの品質のために U を任意に設定できる。 |
U != 0, K > U | カーネルのメモリを使用するため、コンテナ向けに両方のメモリが、ユーザ・カウンタと再利用トリガに影響を与えます。 |
例:
$ docker run -ti -m 500M –kernel-memory 50M ubuntu:14.04 /bin/bash
メモリとカーネルメモリを設定しました。これにより、コンテナ内のプロセスは合計 500M まで使えます。この 500M のメモリのうち、トップに 50M のカーネル・メモリがあります。
$ docker run -ti --kernel-memory 50M ubuntu:14.04 /bin/bash
-m オプションを指定せずカーネル・メモリを指定しました。そのため、コンテナ内のプロセスは必要なだけ多くのメモリを利用可能ですが、そこに最低限 50M のカーネル・メモリを使います。
スワップ回避(swappiness)制限¶
デフォルトでは、コンテナのカーネルは、アノニマス・ページ・メモリ上の何パーセントかをスワップ・アウトします。コンテナ向けのこのパーセントを指定するには --memory-swappiness
で 0 ~ 100 までの値を設定します。この値が 0 であればアノニマス・ページのスワッピング(anonymous page swapping)を無効にします。値を 100 にすると全てのページがスワップ可能となります。デフォルトでは、 --memory-swappiness
を指定しなければ、メモリのスワップ回避(swappiness)は親の値を継承します。
例:
$ docker run -ti --memory-swappiness=0 ubuntu:14.04 /bin/bash
--memory-swappiness
オプションが役立つのは、コンテナの作業セットを維持し、スワップによるパフォーマンスのペナルティを避ける場合です。
CPU 共有制限¶
デフォルトでは、全てのコンテナは同じ CPU サイクルの割合を持っています。この割合は変更可能なものであり、コンテナの CPU 共有ウエイトを、実行中の全てのコンテナに対する相対的な値として変更できます。
割合をデフォルトの 1024 から変更するには、 -c
か --cpu-shares
フラグでウエイトを 2 以上の値で設定します。もし 0 を設定しても、システムは値を無視してデフォルトの 1024 を使います。
割合が適用されるのは CPU に対する処理が集中する時のみです。あるコンテナのタスクがアイドル(何もしていない待機状態)であれば、他のコンテナは CPU 時間の余剰を利用できます。実際に割り当てられる CPU 時間の量は、システム上で実行するコンテナの下図に非常に依存します。
例えば、3つのコンテナがあるとしましょう。1つめの CPU 共有は 1024 で、残り2つの CPU 共有は 512 とします。もし3つのコンテナが CPU を 100% 使用している状態になれば、1つめのコンテナが合計 CPU 時間の 50% を扱えます。4つめのコンテナを CPU 共有 1024 として追加したら、1つめのコンテナが得られるのは CPU の 33% になります。そして、残りの2つめ以降のコンテナが得られる CPU 時間は、それぞれ 16.5%(2つめ)、16.5%(3つめ)、33% (4つめ)となります。
複数のコアを持つ(マルチ・コア)システム上では、全ての CPU コアに分散してCPU 時間が共有されます。コンテナが CPU 時間の 100% より低く制限していても、個々の CPU コアでは 100% 利用できます。
例えば、システムが3つ以上のコアを持っていると想定してみましょう。1つめのコンテナ {C0}
では -c=512
を指定し、1つのプロセスを実行するものとします。そして、他のコンテナ {C1}
は -c=1024
を指定し、2つのプロセスを実行するとします。この結果、CPU 共有は個々のコアに分散されます。
PID container CPU CPU share
100 {C0} 0 100% of CPU0
101 {C1} 1 100% of CPU1
102 {C1} 2 100% of CPU2
CPU 周期(period)制約¶
デフォルトの CPU CFS(Completely Fair Scheduler)周期は 100 ミリ秒です。コンテナの CPU 使用率を制限するには、 --cpu-period
で CPU の周期を制限します。そして、通常の --cpu-period
は --cpu-quota
と一緒に使われるでしょう。
例:
$ docker run -ti --cpu-period=50000 --cpu-quota=25000 ubuntu:14.04 /bin/bash
もし1 CPU であれば、コンテナは 50 ミリ秒ごとに CPU の 50% を利用できます(訳者注:–cpu-quota のクォータ値が、 –cpu-period 周期の半分のため)。
より詳しい情報については、CFS ドキュメントの帯域制限について(英語) をご覧ください。
CPU セット制限¶
どの CPU でコンテナを実行するか指定できます。
例:
$ docker run -ti --cpuset-cpus="1,3" ubuntu:14.04 /bin/bash
これはコンテナ内のプロセスを cpu 1 と cpu 3 で実行します。
$ docker run -ti --cpuset-cpus="0-2" ubuntu:14.04 /bin/bash
こちらはコンテナ内のプロセスを cpu 0 、cpu 1 、 cpu 2 で実行します。
NUMA system 上でのみ、どのコンテナをメモリ上で実行するか設定できます。
$ docker run -ti --cpuset-mems="1,3" ubuntu:14.04 /bin/bash
この例ではコンテナ内でのプロセスを、メモリ・ノード 1 と 3 上のメモリのみに使用を制限します。
$ docker run -ti --cpuset-mems="0-2" ubuntu:14.04 /bin/bash
この例ではコンテナ内でのプロセスを、メモリ・ノード 0と1と2 上のメモリのみに使用を制限します。
CPU クォータ制限¶
--cpu-quota
フラグはコンテナの CPU 使用を制限します。デフォルト値 0 の場合、コンテナは CPU リソース( 1 CPU )の 100% を扱えます。CFS (Completely Fair Scheduler) がプロセス実行時のリソース割り当てを扱っており、これがカーネルによってデフォルトの Linux スケジューラとして使われています。この値を 50000 に指定したら、コンテナは CPU リソースの 50% までの使用に制限されます。複数の CPU の場合は、 --cpu-quota
の調整が必要です。より詳しい情報については、CFS ドキュメントの帯域制限について(英語) をご覧ください。
ブロック IO 帯域(blkio)制限¶
デフォルトでは、全てのコンテナはブロック IO 帯域(blkio)を同じ割合で取得します。デフォルトの割合は 500 です。割合を変更するには --blkio-weight
フラグを使い、実行中の全てのコンテナに対する装置亜的な blkio ウエイトを指定します。
--blkio-weight
フラグは、 10 ~ 1000 までのウエイト値を設定できます。例えば、次のコマンドは2つのコンテナに対し、別々の blkio ウエイトと設定しています。
$ docker run -ti --name c1 --blkio-weight 300 ubuntu:14.04 /bin/bash
$ docker run -ti --name c2 --blkio-weight 600 ubuntu:14.04 /bin/bash
例えば、次のようにして2つのコンテナで同時にブロック IO を確認できます。
$ time dd if=/mnt/zerofile of=test.out bs=1M count=1024 oflag=direct
2つのコンテナ間の blkio ウエイトの割合により、処理にかかる時間の割合が変わるのが分かるでしょう。
注釈
blkio ウエイトの設定は直接 IO (direct IO) のみです。現時点ではバッファ IO (buffered IO) をサポートしていません。
グループの追加¶
--group-add: 実行時のグループを追加
Docker コンテナのプロセスを実行できるのは、デフォルトでは、補助的なグループに所属しているユーザのみです(訳者注:docker グループに所属するユーザ)。グループを更に追加したい場合は、このフラグを使います。
$ docker run --rm --group-add audio --group-add nogroup --group-add 777 busybox id
uid=0(root) gid=0(root) groups=10(wheel),29(audio),99(nogroup),777
実行時の権限、Linux 機能、LXC 設定¶
--cap-add: Linux ケーパビリティの追加
--cap-drop: Linux ケーパビリティの削除(ドロップ)
--privileged=false: コンテナに拡張権限を与える
--device=[]: --privileged(特権)フラグが無いコンテナ内でもデバイスの実行を許可
--lxc-conf=[]: カスタム lxc オプションの追加
デフォルトでは、Docker コンテナは「unprivileged」(権限が無い)ため、Docker コンテナの中で Docker デーモンを動かす等ができません。これは、デフォルトのコンテナはあらゆるデバイスに対して接続できないためであり、「privileged」(特権)コンテナのみが全てのコンテナに接続できます( lxc-template.go と cgroups devices のドキュメントをご覧ください )
作業者が docker run --privileged
を実行したら、Docker はホスト上の全てのデバイスに対して接続可能になります。この時、 AppArmor や SELinux の設定があれば、ホスト上のコンテナ外のプロセスと同じように、ホスト上の同じアクセス権限が与えられた状態で利用可能になります。 --privileged
の実行に関する追加情報については、 Docker ブログの投稿(英語) をご覧ください。
特定のデバイスに対する許可だけ加えたい時は、 --device
フラグが使えます。これを指定したら、1つまたは複数のデバイスがコンテナ内から接続できるようになります。
$ docker run --device=/dev/snd:/dev/snd ...
デフォルトでは、コンテナはデバイスに対して read
、 write
、 mknod
が可能です。それぞれの --device
フラグは、 :rwm
という3つのオプション・セットで上書きできます。
$ docker run --device=/dev/sda:/dev/xvdc --rm -it ubuntu fdisk /dev/xvdc
Command (m for help): q
$ docker run --device=/dev/sda:/dev/xvdc:r --rm -it ubuntu fdisk /dev/xvdc
You will not be able to write the partition table.
Command (m for help): q
$ docker run --device=/dev/sda:/dev/xvdc:w --rm -it ubuntu fdisk /dev/xvdc
crash....
$ docker run --device=/dev/sda:/dev/xvdc:m --rm -it ubuntu fdisk /dev/xvdc
fdisk: unable to open /dev/xvdc: Operation not permitted
--privileged
に加え、作業者は --cap-add
と --cap-drop
を使い、ケーパビリティに対する詳細な制御が可能になります。デフォルトでは、Docker はデフォルトのケーパビリティ一覧を保持しています。次の表は、追加・削除可能な Linux ケーパビリティのオプション一覧です。
ケーパビリティのキー(capability key) | ケーパビリティの説明 |
---|---|
SETPCAP | プロセスの機能を変更 |
SYS_MODULE | カーネル・モジュールのロード(load)・アンロード(unload) |
SYSRAWIO | ランダム I/O ポート操作 (iopl(2) と ioperm(2)). |
SYS_PACCT | acct(2) を用いたプロセスのスイッチ回数のカウント有無 |
SYS_ADMIN | システム管理オペレーションの処理範囲 |
SYS_NICE | プロセスの nice 値 (nice(2), setpriority(2)) を上げるのと、任意プロセスに対する nice 値を設定 |
SYS_RESOURCE | リソース上限の上書き |
SYS_TIME | システム・クロック (settimeofday(2), stime(2), adjtimex(2)) の設定 |
SYS_TTY_CONFIG | vhangup(2) を使用。仮想ターミナル上で ioctl(2) オペレーションの関連権限 |
MKNOD | mknod(2) で特別ファイルを作成 |
AUDIT_WRITE | カーネル監査( auditing )ログに記録 |
AUDIT_CONTROL | カーネルの監査( auditing )を有効化。監査フィルタルールの変更や、監査状態やフィルタリング・ルールの読み出し |
MAC_OVERRIDE | MAC 設定や状態の変更。Smack LSM 用の実装 |
MAC_ADMIN | Mandatory アクセス・コントロール(MAC)の上書き。Smack Linux Security Module (LSM) 用の実装 |
NET_ADMIN | 様々なネットワーク関連処理の実施 |
SYSLOG | 特権 syslog(2) 処理の実施 |
CHOWN | ファイルの UID と GID 属性を変更( chown(2) を参照) |
NET_RAW | RAW と PACKET ソケットを使用 |
DAC_OVERRIDE | ファイル音読み書き実行時に迂回し、権限を確認 |
FOWNER | 操作権限の確認時に迂回し、ファイルの UID がシステム上で必要とする UID と一致するか確認 |
DAC_READ_SEARCH | ファイル読み込み権限の確認を迂回し、ディレクトリの読み込み・実行権限を確認 |
FSETID | ファイル変更時にユーザ ID とグループ ID を変更しない |
KILL | シグナル送信時の権限確認をバイパス |
SETGID | プロセス GID を GID 一覧にある任意のものに変更 |
SETUID | プロセス UID を任意のものに変更 |
LINUX_IMMUTABLE | FS_APPEND_FL と FS_IMMUTABLE_FL i-node フラグを設定 |
NET_BIND_SERVICE | ソケットをインターネット・ドメイン権限用のポート(ポート番号は 1024 以下)に割り当て |
NET_BROADCAST | ソケットをブロードキャストし、マルチキャストをリッスンする |
IPC_LOCK | メモリのロック(mlock(2), mlockall(2), mmap(2), shmctl(2)) |
IPC_OWNER | System V IPC オブジェクト操作用の権限確認 |
SYS_CHROOT | chroot(2) を使い、ルート・ディレクトリを変更 |
SYS_PTRACE | ptrace(2) を使い、任意のプロセスをトレース |
SYS_BOOT | reboot(2) と kexec_load(2) を使い、後の処理用にリブートと新しいカーネルを読み込み |
LEASE | 任意のファイルのリースを確立(詳細は fcntl(2) ) |
SETFCAP | ファイルの機能を設定 |
WAKE_ALARM | システムを起動する何らかのトリガ |
BLOCK_SUSPEND | ブロック・システムをサスペンドする機能 |
より詳細なリファレンス情報は Linux man ページの capabilities(7) をご覧ください。
作業者は全ての機能を有効化するために ALL
値を使えますが 、 MKNOD
だけ除外したい時は次のようにします。
$ docker run --cap-add=ALL --cap-drop=MKNOD ...
ネットワーク・スタックとやりとりするには、 --privileged
を使う替わりに、ネットワーク・インターフェースの変更には --cap-add=NET_ADMIN
を使うべきでしょう。
$ docker run -t -i --rm ubuntu:14.04 ip link add dummy0 type dummy
RTNETLINK answers: Operation not permitted
$ docker run -t -i --rm --cap-add=NET_ADMIN ubuntu:14.04 ip link add dummy0 type dummy
FUSE を基盤とするファイルシステムをマウントするには、 --cap-add
と --device
の両方を使う必要があります。
$ docker run --rm -it --cap-add SYS_ADMIN sshfs sshfs sven@10.10.10.20:/home/sven /mnt
fuse: failed to open /dev/fuse: Operation not permitted
$ docker run --rm -it --device /dev/fuse sshfs sshfs sven@10.10.10.20:/home/sven /mnt
fusermount: mount failed: Operation not permitted
$ docker run --rm -it --cap-add SYS_ADMIN --device /dev/fuse sshfs
# sshfs sven@10.10.10.20:/home/sven /mnt
The authenticity of host '10.10.10.20 (10.10.10.20)' can't be established.
ECDSA key fingerprint is 25:34:85:75:25:b0:17:46:05:19:04:93:b5:dd:5f:c6.
Are you sure you want to continue connecting (yes/no)? yes
sven@10.10.10.20's password:
root@30aa0cfaf1b5:/# ls -la /mnt/src/docker
total 1516
drwxrwxr-x 1 1000 1000 4096 Dec 4 06:08 .
drwxrwxr-x 1 1000 1000 4096 Dec 4 11:46 ..
-rw-rw-r-- 1 1000 1000 16 Oct 8 00:09 .dockerignore
-rwxrwxr-x 1 1000 1000 464 Oct 8 00:09 .drone.yml
drwxrwxr-x 1 1000 1000 4096 Dec 4 06:11 .git
-rw-rw-r-- 1 1000 1000 461 Dec 4 06:08 .gitignore
....
デフォルトの seccomp profile は特定のケーパビリティでファシリティを使えるようになりました。そのため Docker 1.12 から調整は不要です。Docker 1.10 と Docker 1.11 では何も起こりませんので、カスタム seccomp profile を使うか --security-opt seccomp=unconfined
でケーパビリティを追加します。
ログ記録ドライバ(–log-driver)¶
Docker デーモンはコンテナごとに異なったログ記録ドライバを指定できます。コンテナのログ記録ドライバを指定するには、 docker run
コマンドで --log-driver=VALUE
を指定します。以下のオプションがサポートされています。
none |
コンテナのログ記録ドライバを無効化します。このドライバでは docker logs が機能しません。 |
json-file |
Docker に対応するデフォルトのログ記録ドライバです。ファイルに JSON メッセージを書き込みます。このドライバに対するオプションはありません。 |
syslog |
Docker に対応する Syslog ログ記録ドライバです。ログのメッセージを syslog に書き込みます。 |
journald |
Docker に対応する Journald ログ記録ドライバです。ログのメッセージを journald に書き込みます。 |
fluentd |
Docker に対応する Fluentd ログ記録ドライバです。ログ・メッセージを fluentd に書き込みます(forward input)。 |
awslogs |
Docker に対応する Amazon CloudWatch Logs ロギング・ドライバです。ログ・メッセージを Amazon CloudWatch Logs に書き込みます。 |
docker logs
コマンドが使えるのは json-file
と journald
ログ記録ドライバのみです。ログ記録ドライバの詳細な情報については ログ記録ドライバの設定 をご覧ください。
Dockerfile イメージのデフォルトより優先¶
開発者は Dockerfile を使ってイメージ構築時やコミット時、対象イメージを使ったコンテナを起動時に有効な各種パラメータを、開発者自身が設定できます。
実行時に4つのコマンド FROM
、 MAINTAINER
、 RUN
、 ADD
は上書きできません。それ以外のコマンド全ては docker run
で上書きできます。開発者が Dockerfile で個々の命令を設定していたとしても、作業者はその設定を上書きして操作できます。
- CMD(デフォルトのコマンドかオプション)
- ENTRYPOINT(実行時に処理するデフォルトのコマンド)
- EXPOSE (露出用のポート)
- ENV(環境変数)
- VOLUME(共有ファイルシステム)
- USER
- WORKDIR
CMD(デフォルトのコマンドかオプション)¶
Docker コマンドラインでのオプション コマンド
を取り消します。
$ docker run [オプション] イメージ[:タグ|@DIGEST] [コマンド] [引数...]
このコマンドは様々なオプションを指定します。 イメージ
の作者が Dockerfile の CMD
命令を使い、デフォルトの コマンド
を既に設定している場合があるためです。作業者(イメージからコンテナを実行する人)は、 CMD
命令を上書きして新しい コマンド
を実行します。
イメージに ENTRYPOINT
も指定されていれば、 CMD
や コマンド
は ENTRYPOINT
に対する引数となります。
ENTRYPOINT(実行時に処理するデフォルトのコマンド)¶
--entrypoint="": Overwrite the default entrypoint set by the image
イメージの ENTRYPOINT
は コマンド
と似ています。これはコンテナを開始する時に実行するコマンドを指定しているためです。しかし、こちらは(意図的に)上書きを難しくしています。 ENTRYPOINT
が提供するのは、コンテナ自身が持つデフォルトの特性や振る舞いです。そのため ENTRYPOINT
を指定しておけば、コンテナ実行時、あたかもコンテナ自身をバイナリのようにして実行可能です。その場合は、デフォルトのオプションを持っているでしょうし、あるいは自分で コマンド
を指定してオプションを指定することも可能です。しかし、時々オペレータはコンテナの中で何らかのコマンドを実行したい場合もあるでしょう。例えば、デフォルトの ENTRYPOINT
の代わりに、自分で ENTRYPOINT
を新たに指定したい場合です。次の例はコンテナ上でシェルを実行するものであり、同様に何らかのもの( /usr/bin/redis-server
のように )を自動的に起動できます。
$ docker run -i -t --entrypoint /bin/bash example/redis
あるいは、次の2つの例は ENTRYPOINT に更にパラメータを渡すものです。
$ docker run -i -t --entrypoint /bin/bash example/redis -c ls -l
$ docker run -i -t --entrypoint /usr/bin/redis-cli example/redis --help
EXPOSE (露出用のポート)¶
run
コマンドには、コンテナのネットワークに対応する以下のオプションがあります。
--expose=[]: コンテナ内のポートまたはポート範囲を露出する
これらは「EXPOSE」命令の露出ポートに追加する
-P=false : 全ての露出ポートをホスト側インターフェースに公開する
-p=[] : コンテナのポートまたはポート範囲をホスト側に公開する
書式: ip:ホスト側ポート:コンテナ側ポート | ip::コンテナ側ポート | ホスト側ポート:コンテナ側ポート | コンテナ側ポート
ホスト側ポートとコンテナ側のポートは、どちらもポート範囲を指定可能です。
両方で範囲を指定した時は、コンテナ側のポート範囲とホスト側のポート範囲が
一致する必要があります。例:
-p 1234-1236:1234-1236/tcp
ホスト側のポート範囲しか指定しない時は、コンテナ側ポートが範囲になるとは限りません。
このような場合、コンテナ側で公開されるポートはホスト側のポート範囲のいずれかです。
(例 -p 1234-1236:1234/tcp )
(実際の割り当てを確認するには ``docker port`` を使う)
--link="" : 他のコンテナに対するリンクを追加 (<名前 or id>:エイリアス or <名前 or id>)
イメージの開発者は、EXPOSE
命令以外のネットワーク機能に関する管理は行えません。 EXPOSE
命令が定義するのは、サービスが初期化時に提供する受信用ポートです。このポートはコンテナの中のプロセスが利用可能にします。作業者は --expose
オプションを使い、公開用ポートを追加できます。
コンテナの内部ポートを露出(expose)するために、オペレータはコンテナ実行時に -P
か -p
フラグを使えます。公開用のポートはホスト上でアクセス可能であり、そのポートはホストに到達可能なクライアントであれば誰でも利用できます。
-P
オプションはホスト・インターフェース上に全てのポートを公開します。Docker は公開されたポートを、ホスト側のポートに対してランダムに拘束(bind)します。このポートの範囲を エフェメラル・ポート範囲(ephemeral port range) と呼び、 /proc/sys/net/ipv4/ip_local_port_range
によって定義されています。 -p
フラグを使うと、特定のポートやポートの範囲を割り当てます。
コンテナ内のポート番号(サービスがリッスンしているポート番号)は、コンテナの外に露出するポート番号(クライアントが接続する番号)と一致させる必要がありません。例えば、コンテナ内の HTTP サービスがポート 80 をリッスンしているとします(そして、イメージ開発者は Dockerfile で EXPOSE 80
を指定しているでしょう )。実行する時に、ホスト側のポート 42800 以上が使われます。公開用ポートがホスト側のどのポートに割り当てられたかを確認するには、 docker port
コマンドを使います。
デフォルトのブリッジ・ネットワークにおいて、新しいクライアント・コンテナの起動時にオペレータが --link
を指定したら、クライアント・コンテナはプライベートなネットワーク・インターフェースを経由して公開ポートにアクセスできます。 Docker ネットワーク概要 にあるユーザ定義ネットワーク上で --link
を指定したら、コンテナをリンクするためのエイリアス名を作成します。
ENV(環境変数)¶
新しいコンテナの作成時、Docker は以下の環境変数を自動的に設定します。
変数 | 値 |
---|---|
HOME |
USER の値を元にして指定 |
HOSTNAME |
コンテナに関連づけるホスト名 |
PATH |
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin のような一般的なディレクトリを含む |
TERM |
コンテナが疑似ターミナル(pseudo-TTY)を割り当てるときは xterm |
更に、オペレータはコンテナに対して 環境変数の組み合わせ を -e
フラグで追加できます。先ほど言及した環境変数や、開発者が Dockerfile の中で ENV
で定義済みの環境変数を上書きできます。
$ docker run -e "deep=purple" --rm ubuntu /bin/bash -c export
declare -x HOME="/"
declare -x HOSTNAME="85bc26a0e200"
declare -x OLDPWD
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
declare -x PWD="/"
declare -x SHLVL="1"
declare -x container="lxc"
declare -x deep="purple"
似たようなものとして、オペレータは -h
で hostname (ホスト名) も定義できます。
HEALTHCHECK(ヘルスチェック)¶
--health-interval チェックを実行する間隔
--health-retries 障害を報告するまでに必要な連続失敗回数
--health-timeout チェックを実行できる最長時間
--no-healthcheck コンテナ固有のヘルスチェックを無効化
例:
$ docker run --name=test -d \
--health-cmd='stat /etc/passwd || exit 1' \
--health-interval=2s \
busybox sleep 1d
$ sleep 2; docker inspect --format='{{.State.Health.Status}}' test
healthy
$ docker exec test rm /etc/passwd
$ sleep 2; docker inspect --format='{{json .State.Health}}' test
{
"Status": "unhealthy",
"FailingStreak": 3,
"Log": [
{
"Start": "2016-05-25T17:22:04.635478668Z",
"End": "2016-05-25T17:22:04.7272552Z",
"ExitCode": 0,
"Output": " File: /etc/passwd\n Size: 334 \tBlocks: 8 IO Block: 4096 regular file\nDevice: 32h/50d\tInode: 12 Links: 1\nAccess: (0664/-rw-rw-r--) Uid: ( 0/ root) Gid: ( 0/ root)\nAccess: 2015-12-05 22:05:32.000000000\nModify: 2015..."
},
{
"Start": "2016-05-25T17:22:06.732900633Z",
"End": "2016-05-25T17:22:06.822168935Z",
"ExitCode": 0,
"Output": " File: /etc/passwd\n Size: 334 \tBlocks: 8 IO Block: 4096 regular file\nDevice: 32h/50d\tInode: 12 Links: 1\nAccess: (0664/-rw-rw-r--) Uid: ( 0/ root) Gid: ( 0/ root)\nAccess: 2015-12-05 22:05:32.000000000\nModify: 2015..."
},
{
"Start": "2016-05-25T17:22:08.823956535Z",
"End": "2016-05-25T17:22:08.897359124Z",
"ExitCode": 1,
"Output": "stat: can't stat '/etc/passwd': No such file or directory\n"
},
{
"Start": "2016-05-25T17:22:10.898802931Z",
"End": "2016-05-25T17:22:10.969631866Z",
"ExitCode": 1,
"Output": "stat: can't stat '/etc/passwd': No such file or directory\n"
},
{
"Start": "2016-05-25T17:22:12.971033523Z",
"End": "2016-05-25T17:22:13.082015516Z",
"ExitCode": 1,
"Output": "stat: can't stat '/etc/passwd': No such file or directory\n"
}
]
}
docker ps
の出力からもヘルス・ステータスを表示できます。
TMPFS (tmfps ファイルシステムのマウント)¶
--tmpfs=[]: tmpfs マウントを作成: コンテナ側ディレクトリ[:<オプション>],
オプションは Linux コマンドの 'mount -t tmpfs -o' オプションと同一形式
この例では、オプションで rw
、 noexec
、 nosuid
、 size=65536k
、コンテナに対して空の tmpfs をマウントしています。
$ docker run -d --tmpfs /run:rw,noexec,nosuid,size=65536k my_image
VOLUME(共有ファイルシステム)¶
-v=[]: バインド(拘束)マウントを作成: [ホスト側ディレクトリ:]コンテナ側ディレクトリ[:<オプション>]
オプションはカンマ区切りで [rw|ro] または [z|Z]、[[r]shared|[r]slave|[r]private]、そして [nocopy] から選択
host-src
は絶対パスもしくは名前を値にします。
rw
(読み書き)または ro
(読み込み専用)の指定が無ければ、読み書き可能なモードでマウントします。
nocopy
モードを指定したら、コンテナ内に要求したボリューム・パスに対して、ボリュームを保存している場所からの自動コピーを無効にします。名前付きボリュームの場合は、 copy
がデフォルトのモードです。コピー・モードではバインド・マウント(bind-mounted)したボリュームに対するコピーをサポートしていません。
--volumes-from="": 指定したコンテナにある全てのボリュームをマウント
注釈
Docker デーモンの開始・停止を systemd で管理する場合は、 Docker デーモン自身がマウント・プロパゲーション(mount propagation)を管理できるよう、systemd の unit ファイル上で MountFlags
というオプションを設定します。このマウントポイントが変更されても、Docker はマウント・プロパゲーションの変更を把握できません。例えば、値を slave
としているのであれば、ボリュームのプロパゲーション値に shared
や rshared
を指定すべきではないでしょう。
ボリューム関連コマンドは /engine/userguide/containers/dockervolumes セクション自身のドキュメントでも複雑なものです。開発者は1つまたは複数の VOLUME
を作成し、イメージと関連づけることが可能です。しかし、作業者ができるのは、あるコンテナから別のコンテナに対してのみです(あるいは、コンテナからホスト側のボリュームにマウントする場合)。
コンテナ側ディレクトリ
は /src/docs
のように常に絶対パスの必要があります。 ホスト側ディレクトリ
は絶対パスか 名前
を値に指定できます。 ホスト側ディレクトリ
に絶対パスを指定する場合は、 Docker は指定したパスを拘束マウント(bind-mounts)します。 名前
を指定する場合は、Docker は 名前
を持つボリュームを作成します。
名前
は英数字で始まる必要があり、以降は a-z0-9
、_
(アンダースコア)、 .
(ピリオド)、 -
(ハイフン)が使えます。絶対パスは /
(フォアワード・スラッシュ)で始める必要があります。
例えば、 ホスト側ディレクトリ
の値に /foo
か foo
を指定したとします。 /foo
値を指定した場合は、Docker はホスト上に拘束マウントを作成します。 foo
を指定したら、Docker は指定された名前でボリュームを作成します。
USER¶
開発者は Dockerfile の USER
命令を使い、1つめのプロセスを実行する時のユーザを定義できます。コンテナ起動時に -u
オプションを使うと USER
命令を上書きできます。
-u="", --user="": ユーザ名または UID を指定する命令。オプションでグループ名や GUID を指定
以下は有効な例です。
--user=[ user | user:group | uid | uid:gid | user:gid | uid:group ]
注釈
数値で UID を指定する場合は、0 ~ 2147483647 の範囲内の必要があります。
WORKDIR¶
コンテナ内でバイナリを実行する時、デフォルトの作業用ディレクトリはルート( /
) ディレクトリです。しかし開発者は Dockerfile の WORKDIR
コマンドを使い、デフォルトの作業用ディレクトリを変更できます。作業者が更に設定を上書きするには、次のようにします。
-w="": コンテナ内の作業用(ワーキング)ディレクトリ
参考
- Docker run reference
- https://docs.docker.com/engine/reference/run/