【トラブルシューティング】Docker (daemon) の手動起動、デバッグ・ログ出力に関して調べてみた

Dockerのトラブルシューティングがうまくできるようになりたいと思い

に関して調べてみました。

今回使用したdockerのバージョンは20.10.0です。2020/12/15時点での情報のため、dockerのコマンドや設定ファイルのパス等、今後変更になる可能性があります。

Dockerエンジンの基本的な構成

まず、Dockerエンジンは、以下の図のように主に3つのコンポーネントから構成されています。

  • Docker CLI (dockerコマンド): コンテナやイメージ、ネットワーク等の操作をHTTP経由のAPIを介して、Docker daemonと通信するクライアント。
  • Dockerエンジン API: CLIやプログラムからのHTTP経由で要求を受け付ける。
  • Docker daemon: コンテナの生成、実行、モニタリング等を行い、結果を返す。

f:id:moritamorie:20201216002943p:plain

今回調べたトラブルシューティング時に追えるようになる情報は、Docker daemonの部分です。

デーモンのログ出力を詳細を見れることでデーモンが起動していない場合でも発生したエラーの内容を見れるので、特に普段dockerコマンド(Docker CLI)しか使わないという場合、トラブル対応時に役に立つかと思います。

なお、Docker CLIdocker logs はコンテナのログを出力するものなので、デーモンのログとは別のものです。docker logs にはコンテナ作成時のエラー等は出力されません。

Docker daemonの起動(自動起動)

Dockerをインストールするとシステムユーティリティー(多くのLinuxのディストリの場合Systemd)がOS起動時に自動的にデーモンを起動しています。

試しにdocker.serviceのステータスを確認すると

$ sudo systemctl status docker

● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2020-12-15 16:29:17 JST; 6h ago
     Docs: https://docs.docker.com
 Main PID: 1740 (dockerd)
    Tasks: 80
   CGroup: /system.slice/docker.service
           ├─1740 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
           ├─2987 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 15432 -container-ip 172.22.0.3 -container-port 5432
           └─3059 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 1080 -container-ip 172.22.0.4 -container-port 80

1215 16:29:12 takashi dockerd[1740]: time="2020-12-15T16:29:12.851824229+09:00" level=warning msg="Your kernel does not support swap memory limit"

Main PID: 1740 (dockerd) という出力があり、デーモンが動いているのが確認できるかと思います。

Docker daemonの手動起動

もし、systemd自動起動 or systemd start docker で デーモンが起動できない場合などに、手動でdockerd コマンドを実行して起動することもできます。

基本的には1つのdockerホスト内で複数のdocker daemonを起動できないため、systemdから起動されたデーモンが起動中の場合、新しいデーモンの起動には失敗します。

$ sudo dockerd
INFO[2020-12-15T23:03:29.443621640+09:00] Starting up                                  
failed to start daemon: pid file found, ensure docker is not running or delete /var/run/docker.pid

一旦 systemddocker.service を停止すると起動でき、起動時のログがコンソールに出力されます。

sudo systemctl stop docker
takashi@tamo:/var/lib/docker$ sudo dockerd
INFO[2020-12-15T23:05:18.685050913+09:00] Starting up
INFO[2020-12-15T23:05:18.685967243+09:00] detected 127.0.0.53 nameserver, assuming systemd-resolved, so using resolv.conf: /run/systemd/resolve/resolv.conf 
︙

Docker daemonの設定

自動起動の場合

Linuxの場合 /etc/docker/daemon.json をデーモンの設定ファイルとして自動的に読み込みます。(Mac, Windowの場合はGUI上のPreferences / Daemon / Advancedから設定)

設定できるオプションは様々ありますが、トラブルシューティング時に

  • デバッグモードを有効にし、デーモンからより詳細な出力を得られるようにする(デフォルトは無効)
  • ログレベルをdebugにする(デフォルトはinfo)

という場合は、以下のように記載した設定ファイルを配置します。

{
  "debug": true,
  "log-level": "debug"
}

※設定ファイルの他のオプションに関しては、こちらに記載されています。

Linuxの場合、以下のコマンドでデーモンに対して HUP シグナルを送信し、設定を再読み込みさせることができます。

$ sudo kill -SIGHUP $(pidof dockerd)

手動起動の場合

docker daemon は、設定ファイルを自動的に読み込むようになっていますが、同時に手動起動の場合はオプションも併せて指定することができます。

$ dockerd --debug --log-level debug

設定でオプションを変更したらデーモンが起動しなくなった場合などは、手動起動でどのオプションを変更したら動かなくなるかを確認すると良さそうです。

自動的に読み込まれる設定ファイルとオプションが重複する場合は、以下のようなエラーが発生し、デーモン起動は失敗します。

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])

デーモンのログのパス/確認方法

ログファイルのパス/確認方法はOS毎に異なります。

他のOSのログファイルに関しては、詳細はドキュメント を参照してください。

スタックトレースの確認

デーモンの反応がない場合は、Linuxだと以下のコマンドでスタックトレースを強制的に出力できます。スタックトレースがログに出力されますが、デーモンは停止しません。

$ sudo kill -SIGUSR1 $(pidof dockerd)

Docker deamonの起動確認

いくつかの方法で起動を確認できます。Docker CLIのコマンドを実行して、反応がなかったり、エラーが発生した場合に起動しているか状態を確認すると良さそうです。

  • OSに依らない確認方法
    • Docker CLIを使う
      • docker info
  • OSに依る確認方法
    • Systemdを使う
      • sudo systemctl is-active docker
      • sudo systemctl status docker
      • sudo service docker status
    • プロセスの状態を確認する
      • ps
      • top

参考資料