Docker デーモンの設定とトラブルシュート

読む時間の目安: 4 分

Docker を正常にインストールし Docker を起動すると、dockerdというデーモンがデフォルト設定により起動します。 ここではその設定のカスタマイズ方法、デーモンの手動起動、問題発生時のトラブルシュートやデバッグについて示します。

OS ユーティリティーによるデーモンの起動

標準的なインストールによる Docker デーモンは、ユーザーが手動で起動するものではなく、システムのユーティリティーによって起動されます。 これによりマシン再起動時に、Docker を自動起動させることが簡単になります。

Docker を起動させるコマンドはオペレーティングシステムによります。 Docker のインストール の中から適切なページを確認してください。 システム起動時に Docker を自動起動するように設定する場合は システムブート時の Docker 起動設定 を参照してください。

デーモンの手動起動

Docker デーモンをシステムユーティリティーによって管理することが望ましくない場合、あるいは何かをすぐにテストしたいといった場合、dockerdコマンドを利用してデーモンを手動起動することができます。 このときにはsudoを必要とするかもしれませんが、そこはオペレーティングシステムでの設定によります。

この方法によって Docker を起動した場合、Docker はフォアグラウンド実行され、出力ログは端末に直接出力されます。

$ dockerd

INFO[0000] +job init_networkdriver()
INFO[0000] +job serveapi(unix:///var/run/docker.sock)
INFO[0000] Listening for HTTP on unix (/var/run/docker.sock)

手動で起動させた Docker を停止するには、端末上でCtrl+Cを入力します。

デーモンの設定

Docker デーモンの設定には 2 つの方法があります。

  • JSON 形式の設定ファイルを利用します。 設定をすべて一箇所にとりまとめられるので、この方法が推奨されます。
  • dockerd起動時のフラグを利用します。

同じオプションをフラグと JSON ファイルの両方に指定しない限り、フラグと JSON ファイルによる指定を併用することができます。 もし両方に指定してしまった場合、Docker デーモンは起動せず、エラーメッセージが出力されます。

JSON ファイルを使って Docker デーモンを設定する場合、Linux であればその設定ファイルを/etc/docker/daemon.jsonに、また Windows であればC:\ProgramData\docker\config\daemon.jsonにファイルを生成します。 MacOS の場合は、タスクバー上の Docker アイコンをクリックして Preferences > Daemon > Advanced を実行して設定します。

設定ファイルは以下のようにします。

{
  "debug": true,
  "tls": true,
  "tlscert": "/var/docker/server.pem",
  "tlskey": "/var/docker/serverkey.pem",
  "hosts": ["tcp://192.168.59.3:2376"]
}

この設定によってデーモンを起動すると、デバッグモードとなり TLS を利用し、192.168.59.32376ポートへのトラフィックを待ち受けるものとなります。 どのような設定オプションが利用可能であるかは、dockerd リファレンスドキュメント を参照してください。

また Docker デーモンを手動で起動し、その際にフラグを使って設定することもできます。 これはトラブルを解決するときに活用できる方法です。

以下の例は Docker デーモンを手動で起動する方法であり、先ほどと同じ設定を行うものです。

$ dockerd --debug \
  --tls=true \
  --tlscert=/var/docker/server.pem \
  --tlskey=/var/docker/serverkey.pem \
  --host tcp://192.168.59.3:2376

どのような設定オプションが利用可能であるかは、dockerd リファレンスドキュメント を参照するるか、あるいは以下を実行してみてください。

$ dockerd --help

Docker ドキュメントでは、設定オプションを数多く取り扱っています。 その中から次に見ていくものとして、以下をあげておきます。

Docker デーモンディレクトリ

Docker デーモンは関連データをすべて、単一のディレクトリ配下に保持します。 ここに Docker に関連する、コンテナー、イメージ、ボリューム、サービス定義、機密情報などすべて管理しています。

このディレクトリはデフォルトでは以下のものです。

  • Linux では /var/lib/docker
  • Windows では C:\ProgramData\docker

設定オプションのdata-rootというものを使えば、Docker デーモンが利用するディレクトリを別のところに変更することもできます。

Docker デーモンの状態はこのディレクトリ内に保持されるので、デーモンごとに専用のディレクトリを利用することが必要です。 2 つあるデーモンが、たとえば NFS 共有による同一のディレクトリをともに利用していると、解決困難なエラーに出会うことになりかねません。

デーモンのトラブルシューティング

デーモンのデバッグ機能を有効にすれば、デーモン実行時の様子を見たり、トラブル解決に役立てたりすることができます。 デーモンが完全に応答しなくなった場合は、全スレッドに対して スタックトレースの強制出力 が可能です。 これは Docker デーモンに対してSIGUSRシグナルを送信すれば、デーモンログに出力されます。

daemon.jsonと起動スクリプトの競合を解決する

daemon.jsonファイル利用時であって、同じオプションをdockerdコマンドに対して手動で指定した場合、あるいは起動スクリプト実行をした場合、そのオプションが競合してしまい、以下のようなエラーが出力されてデーモン起動は失敗します。

unable to configure the Docker daemon with file /etc/docker/daemon.json:
the following directives are specified both as a flag and in the configuration
file: hosts: (from flag: [unix:///var/run/docker.sock], from file: [tcp://127.0.0.1:2376])

上のようなエラーが出力され、デーモンの手動起動時にフラグ設定を行っているなら、そのフラグを正しくするか、あるいはdaemon.json内から競合しているフラグを削除します。

メモ: 上のエラーが出力された場合、とりあえずの解決としては 次節 に進んでください。

オペレーティングシステムの初期化スクリプトにより Docker デーモンを起動している場合は、そのスクリプト内におけるデフォルト設定を上書きすることになるかもしれません。 その方法については、オペレーティングシステムが規定する方法に従ってください。

systemd を使った daemon.json 内での hosts キーの利用

競合が発生してもわかりにくい例として、よくあるのが、デーモンのアドレスをデフォルトとは異なるものにした場合です。 Docker はデフォルトでソケットを待ち受けます。 Debian や Ubuntu はsystemdを利用しているので、dockerdの起動時には必ず、ホスト指定に-Hフラグを用います。 daemon.jsonファイルにhost項目を指定した場合、設定の競合が発生して(上で示したメッセージが出力され)Docker の起動は失敗します。

この問題をとりあえず回避するには/etc/systemd/system/docker.service.d/docker.confというファイルを生成し、内容を以下のようにします。 これはデフォルトにおいて、デーモン起動時に用いられる-H引数を取り除くものです。

[Service]
ExecStart=
ExecStart=/usr/bin/dockerd

Docker に関してsystemdの設定を見直す必要が、他にも出てくるかもしれません。 たとえば HTTP または HTTPS プロキシーの設定 を行う必要がある場合です。

メモ: このオプションを上のように設定したにもかかわらず、daemon.jsonhosts設定や、Docker 手動起動時の-Hフラグを用いなかった場合には、Docker の起動は失敗します。

Docker を起動しようとする前にはsudo systemctl daemon-reloadを実行してください。 Docker が正常に起動したら、これ以降はソケットを待ち受けるのでなく、daemon.jsonhostsキーに指定された IP アドレスからのトラフィックを待ち受けることになります。

重要: daemon.jsonにおいてhostsの設定を行う方法は、Docker Desktop for Windows や Docker Desktop for Mac ではサポートされていません。

Out Of Memory Exceptions (OOME)

コンテナーの利用するメモリ容量が、システムの残容量を超えた場合に、Out Of Memory Exception (OOME) が発生することがあります。 その場合コンテナーあるいは Docker デーモンは、カーネルの OOM キラーによって kill されるかもしれません。 このような発生を防ぐためには、ホスト上の適切なメモリ容量範囲内でアプリケーションが動作するようにしてください。 out of memory となるリスクの理解 も確認してください。

ログを読む

デーモンログは、問題の解決に役立つものです。 ログはいくつかの場所に保存されます。 これはオペレーティングシステムの設定や、利用しているログ管理システムによって定まります。

オペレーティングシステム 場所
Linux journalctl -xu docker.serviceを実行。 (または/var/log/syslog/var/log/messagesの参照。Linux ディストリビューションにより異なる。)
macOS (dockerd logs) ~/Library/Containers/com.docker.docker/Data/log/vm/dockerd.log
macOS (containerd logs) ~/Library/Containers/com.docker.docker/Data/log/vm/containerd.log
Windows (WSL2) (dockerd logs) AppData\Roaming\Docker\log\vm\dockerd.log
Windows (WSL2) (containerd logs) AppData\Roaming\Docker\log\vm\containerd.log
Windows (Windows containers) ログは Windows イベントログ内に。

macOS 上においてdockerdログを参照するには、端末画面を開いてtailコマンドを使います。 その際には-fフラグをつけることで、ログを追うことができます。 ログの表示は、CTRL+cを入力してコマンドを中止させるまで続きます。

$ tail -f ~/Library/Containers/com.docker.docker/Data/log/vm/dockerd.log
2021-07-28T10:21:21Z dockerd time="2021-07-28T10:21:21.497642089Z" level=debug msg="attach: stdout: begin"
2021-07-28T10:21:21Z dockerd time="2021-07-28T10:21:21.497714291Z" level=debug msg="attach: stderr: begin"
2021-07-28T10:21:21Z dockerd time="2021-07-28T10:21:21.499798390Z" level=debug msg="Calling POST /v1.41/containers/35fc5ec0ffe1ad492d0a4fbf51fd6286a087b89d4dd66367fa3b7aec70b46a40/wait?condition=removed"
2021-07-28T10:21:21Z dockerd time="2021-07-28T10:21:21.518403686Z" level=debug msg="Calling GET /v1.41/containers/35fc5ec0ffe1ad492d0a4fbf51fd6286a087b89d4dd66367fa3b7aec70b46a40/json"
2021-07-28T10:21:21Z dockerd time="2021-07-28T10:21:21.527074928Z" level=debug msg="Calling POST /v1.41/containers/35fc5ec0ffe1ad492d0a4fbf51fd6286a087b89d4dd66367fa3b7aec70b46a40/start"
2021-07-28T10:21:21Z dockerd time="2021-07-28T10:21:21.528203579Z" level=debug msg="container mounted via layerStore: &{/var/lib/docker/overlay2/6e76ffecede030507fcaa576404e141e5f87fc4d7e1760e9ce5b52acb24
...
^C

デバッグの有効化

デバッグを有効にするには 2 通りあります。 お勧めの方法はdaemon.jsonファイルにおいてdebugキーをtrueにすることです。 この方法はどの Docker プラットフォームでも動作します。

  1. daemon.jsonファイルを編集します。 その場所は通常/etc/docker/にあります。 存在しなければ、ここで生成します。 macOS や Windows の場合、このファイルを直接編集はしません。 そのかわり Preferences / Daemon / Advanced を実行してください。

  2. ファイルが空であれば以下の記述を追加します。

    {
      "debug": true
    }
    

    このファイルにすでに JSON 記述が行われていた場合は"debug": trueというキー項目のみを追加します。 閉じブラケット直前の最終行として追加する場合には、行末にカンマは不要ですが、そうでなければカンマを忘れないでください。 またlog-levelを設定する場合には、その値をinfodebugにしてください。 infoがデフォルト値であり、設定可能な値はdebuginfowarnerrorfatalのいずれかです。

  3. この設定を再読み込みさせるために、デーモンに対してHUPシグナルを送信します。 Linux ホストの場合は以下のコマンドを実行します。

    $ sudo kill -SIGHUP $(pidof dockerd)
    

    Windows ホストの場合は Docker を再起動します。

上のような方法ではなく、デバッグフラグ-Dを手動で利用すれば Docker デーモンの停止と再起動を行うことができます。 ただしこれを行うと、ホストの初期起動スクリプトが生成するものとは異なる環境において Docker が再起動してしまうことがあります。 この場合、デバッグ作業は難しくなります。

スタックトレースの強制ログ出力

デーモンが反応しなくなった場合には、フルスタックトレースをログ出力させるために、デーモンに対してSIGUSR1シグナルを送信します。

  • Linux の場合

    $ sudo kill -SIGUSR1 $(pidof dockerd)
    
  • Windows Server の場合

    docker-signal をダウンロード。

    Get-Process dockerdにより dockerd のプロセス ID を取得。

    --pid=<デーモンのプロセス ID>フラグを使ってモジュールを実行。

これによりスタックトレースがログに出力されますが、デーモンは停止されません。 デーモンログにスタックトレースが出力されているか、あるいはスタックトレースをファイル出力されていれば、そのファイルへのパスが示されています。

デーモンがSIGUSR1シグナルを処理した後は、スタックトレースをログ出力した上で、動作を続行します。 スタックトレースからは、デーモン内部で処理されていた Go 言語のゴルーチン(goroutine)やスレッドの状態を確認することができます。

スタックトレースの確認

Docker デーモンログは、以下に示すような方法により確認することができます。

  • systemctlを利用している Linux システム上にてjournalctl -u docker.serviceを実行します。
  • 古い Linux の場合は/var/log/messages/var/log/daemon.log/var/log/docker.logを確認します。

メモ

Docker Desktop for Mac や Docker Desktop for Windows において、スタックトレースをコマンド操作によって取得することはできません。 しかし問題が発生したときには、 Docker タスクバーアイコンをクリックし Troubleshoot を実行すれば、Docker に対して情報を送信することができます。

Docker ログに出力された以下のようなメッセージを見てみます。

...goroutine stacks written to /var/run/docker/goroutine-stacks-2017-06-02T193336z.log
...daemon datastructure dump written to /var/run/docker/daemon-data-2017-06-02T193336z.log

Docker がスタックトレースやダンプを保存する場所は、オペレーティングシステムとその設定によって決まります。 スタックトレースやダンプからは、わかりやすい有用な診断情報が得られることがあります。 そうでないときには、Docker に対してこの情報を提供して、問題解決に役立てることができます。

Docker の起動確認

オペレーティングシステムを問わず Docker が動いているかどうかを確認するにはdocker infoコマンドを実行します。

あるいはオペレーティングシステムが提供するユーティリティーを用いることもできます。 たとえばsudo systemctl is-active dockersudo status dockersudo service docker statusなどです。 また Windows の場合は、サービス状態を確認するユーティリティーを利用します。

またpstopコマンドを使えば、dockerdプロセス内のプロセス一覧を確認することができます。

docker, daemon, configuration, troubleshooting