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つの標準ストリーム( STDINSTDOUTSTDERR )のうち、特定のものに対してのみ接続も可能です。

$ 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 が特別に扱います。デフォルトの操作では、あらゆるシグナルを無視します。そのため、プロセスは SIGINTSIGTERM で停止するようにコードを書かない限り、停止できません。

コンテナの識別

名前(–name)

作業者はコンテナを3つの方法で識別できます。

  • 長い(ロング) UUID 識別子(」f78375b1c487e03c9438c729345e54db9d20cfa2ac1fc3494b6eb60872e74778」)
  • 短い(ショート)UUID 識別子(」f78375b1c487」)
  • 名前(」evil_ptolemy」)

UUID 識別子は Docker デーモンから与えられます。コンテナの名前を --name オプションで割り当てなければ、デーモンはランダムな文字列から名前を生成します。コンテナに対する目的を表すには、 name の定義が簡単でしょう。 name を指定したら、これを Docker ネットワーク内でコンテナを参照用に使えます。この参照機能は、バックグラウンドでもフォアグラウンドどちらの Docker コンテナでも動作します。

注釈

デフォルトのブリッジ・ネットワーク内にあるコンテナの場合は、相互に名前で通信するにはリンクする必要があります。

PID 相当の機能

あとは、自動処理を簡単にするため、Docker は任意に選択したファイルに対してコンテナ ID を書き出せます。これは、プログラムがプロセス ID をファイルに書き出す(いわゆる PID ファイルです)のに似ています。

--cidfile="": コンテナの ID をファイルに書き出す

イメージ[:タグ]

コンテナ実行時のコマンドで イメージ[:タグ] を追加すると、イメージのバージョンを厳密に指定できます。例えば docker run ubuntu:14.04 と実行します。

イメージ[@ダイジェスト値]

イメージ・形式 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 を再利用できるようにします。

コンテナがホスト上の特定のプロセス名前空間を共有する場合は、コンテナ内のプロセスが、システム上の全プロセスを基本的に見られるようにします。例えば、 stracegdb のようなデバッグ用ツールを含むコンテナを構築した時、コンテナ内のデバッグ用プロセスのみツールを使えるように指定する場合です。

例:コンテナ内で 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 名前空間に参加するのは、コンテナのデバッグ用に便利です。

redis サーバが動くコンテナを起動します:

$ docker run --name my-redis -d redis

redis コンテナのデバッグに、strace が入っている他のコンテナを実行。

$ docker run --it --pid=container:my-redis bash
$ strace -p 1

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 処理はファイルに対してか、 STDINSTDOUT のみになります。

公開用のポートを他のコンテナとリンクできるのは、デフォルト(ブリッジ)のみです。リンク機能はレガシー(過去の)機能です。リンク機能を使うよりも、常に 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 でコンテナを見たら、常に UpRestarting のどちらかです。また、再起動ポリシーが有効かどうかを確認するため、 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.gocgroups devices のドキュメントをご覧ください )

作業者が docker run --privileged を実行したら、Docker はホスト上の全てのデバイスに対して接続可能になります。この時、 AppArmor や SELinux の設定があれば、ホスト上のコンテナ外のプロセスと同じように、ホスト上の同じアクセス権限が与えられた状態で利用可能になります。 --privileged の実行に関する追加情報については、 Docker ブログの投稿(英語) をご覧ください。

特定のデバイスに対する許可だけ加えたい時は、 --device フラグが使えます。これを指定したら、1つまたは複数のデバイスがコンテナ内から接続できるようになります。

$ docker run --device=/dev/snd:/dev/snd ...

デフォルトでは、コンテナはデバイスに対して readwritemknod が可能です。それぞれの --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-filejournald ログ記録ドライバのみです。ログ記録ドライバの詳細な情報については ログ記録ドライバの設定 をご覧ください。

Dockerfile イメージのデフォルトより優先

開発者は Dockerfile を使ってイメージ構築時やコミット時、対象イメージを使ったコンテナを起動時に有効な各種パラメータを、開発者自身が設定できます。

実行時に4つのコマンド FROMMAINTAINERRUNADD は上書きできません。それ以外のコマンド全ては docker run で上書きできます。開発者が Dockerfile で個々の命令を設定していたとしても、作業者はその設定を上書きして操作できます。

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"

似たようなものとして、オペレータは -hhostname (ホスト名) も定義できます。

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' オプションと同一形式

この例では、オプションで rwnoexecnosuidsize=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 としているのであれば、ボリュームのプロパゲーション値に sharedrshared を指定すべきではないでしょう。

ボリューム関連コマンドは /engine/userguide/containers/dockervolumes セクション自身のドキュメントでも複雑なものです。開発者は1つまたは複数の VOLUME を作成し、イメージと関連づけることが可能です。しかし、作業者ができるのは、あるコンテナから別のコンテナに対してのみです(あるいは、コンテナからホスト側のボリュームにマウントする場合)。

コンテナ側ディレクトリ/src/docs のように常に絶対パスの必要があります。 ホスト側ディレクトリ は絶対パスか 名前 を値に指定できます。 ホスト側ディレクトリ に絶対パスを指定する場合は、 Docker は指定したパスを拘束マウント(bind-mounts)します。 名前 を指定する場合は、Docker は 名前 を持つボリュームを作成します。

名前 は英数字で始まる必要があり、以降は a-z0-9_ (アンダースコア)、 . (ピリオド)、 - (ハイフン)が使えます。絶対パスは / (フォアワード・スラッシュ)で始める必要があります。

例えば、 ホスト側ディレクトリ の値に /foofoo を指定したとします。 /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/