Dockerデーモンが起動できなくなったときにやったこと

システムのパッケージをアップデートしたら（yum update）、Dockerが使えなくなってしまったので、備忘録としてメモしておきます。
間違っているところがあればご指摘いただけると幸いです。

今回の環境は以下の通りです。

```sh
$ cat /etc/redhat-release 
CentOS Linux release 7.9.2009 (Core)
```

Dockerのバージョンは20.10.17から23.0.6へ、カーネルは3.10.0-1160.76から3.10.0-1160.90へアップデートしたときに発生しました。
```sh
sudo yum history info xx
    ...
    更新     docker-ce-3:20.10.17-3.el7.x86_64                          @docker-ce-stable
    更新               3:23.0.6-1.el7.x86_64                            @docker-ce-stable
    ...
    インストール kernel-3.10.0-1160.90.1.el7.x86_64                         @updates
    更新     kernel-debug-devel-3.10.0-1160.76.1.el7.x86_64             @updates
    更新                        3.10.0-1160.90.1.el7.x86_64             @updates
    インストール kernel-devel-3.10.0-1160.90.1.el7.x86_64                   @updates
    ...
```


## Dockerデーモン（dockerd）が起動していなかったので、起動させようとしてみた
エラーで起動できなかった
```sh
# systemctl start docker
Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.
```

## エラーメッセージのアドバイスに従い、詳細を見てみた

```sh
# systemctl status docker.service
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/docker.service.d
           └─http-proxy.conf
   Active: failed (Result: start-limit) since 木 2023-05-11 16:14:48 JST; 5s ago
     Docs: https://docs.docker.com
  Process: 24696 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock (code=exited, status=1/FAILURE)
 Main PID: 24696 (code=exited, status=1/FAILURE)

 5月 11 16:14:46 localhost.localdomain systemd[1]: Failed to start Docker Ap...
 5月 11 16:14:46 localhost.localdomain systemd[1]: Unit docker.service enter...
 5月 11 16:14:46 localhost.localdomain systemd[1]: docker.service failed.
 5月 11 16:14:48 localhost.localdomain systemd[1]: docker.service holdoff ti...
 5月 11 16:14:48 localhost.localdomain systemd[1]: Stopped Docker Applicatio...
 5月 11 16:14:48 localhost.localdomain systemd[1]: start request repeated to...
 5月 11 16:14:48 localhost.localdomain systemd[1]: Failed to start Docker Ap...
 5月 11 16:14:48 localhost.localdomain systemd[1]: Unit docker.service enter...
 5月 11 16:14:48 localhost.localdomain systemd[1]: docker.service failed.
Hint: Some lines were ellipsized, use -l to show in full.
```

```sh
# journalctl -xeu docker.service
-- Unit docker.service has failed.
-- 
-- The result is failed.
 5月 11 16:14:46 localhost.localdomain systemd[1]: Unit docker.service entered failed state.
 5月 11 16:14:46 localhost.localdomain systemd[1]: docker.service failed.
 5月 11 16:14:48 localhost.localdomain systemd[1]: docker.service holdoff time over, scheduling restart.
 5月 11 16:14:48 localhost.localdomain systemd[1]: Stopped Docker Application Container Engine.
-- Subject: Unit docker.service has finished shutting down
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
-- 
-- Unit docker.service has finished shutting down.
 5月 11 16:14:48 localhost.localdomain systemd[1]: start request repeated too quickly for docker.service
 5月 11 16:14:48 localhost.localdomain systemd[1]: Failed to start Docker Application Container Engine.
-- Subject: Unit docker.service has failed
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
-- 
-- Unit docker.service has failed.
-- 
-- The result is failed.
 5月 11 16:14:48 localhost.localdomain systemd[1]: Unit docker.service entered failed state.
 5月 11 16:14:48 localhost.localdomain systemd[1]: docker.service failed.
```
うーん、わからない・・・

## デバッグオプションを付けて起動してみた
```sh
# dockerd  --debug 
...
de997fc873  storage-driver=devicemapper
WARN[2023-05-11T16:37:19.507770761+09:00] Base device already exists and has filesystem xfs on it. User specified filesystem  will be ignored.  storage-driver=devicemapper
DEBU[2023-05-11T16:37:19.507790198+09:00] deactivateDevice START()                      storage-driver=devicemapper
DEBU[2023-05-11T16:37:19.507849410+09:00] devicemapper:RemoveDeviceDeferred START(docker-253:0-686081-base) 
DEBU[2023-05-11T16:37:19.522229594+09:00] devicemapper: RemoveDeviceDeferred END(docker-253:0-686081-base) 
DEBU[2023-05-11T16:37:19.522281442+09:00] deactivateDevice END()                        storage-driver=devicemapper
ERRO[2023-05-11T16:37:19.522380879+09:00] [graphdriver] prior storage driver devicemapper is deprecated and will be removed in a future release; update the the daemon configuration and explicitly choose this storage driver to continue using it; visit https://docs.docker.com/go/storage-driver/ for more information 
...
```

ストレージドライバはdevicemapperが自動的に選択されたらしい。  
devicemapperを使用するには明示的に指定しないといけないらしい。  


参考：https://github.com/moby/moby/issues/22685

## dockerd起動オプションを確認してみた
/lib/systemd/system/docker.service を開き、ExecStart の行を確認。
```
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
```
ストレージドライバは未指定だった。

## ストレージドライバを指定してDockerデーモンを起動するようにしてみた（Dockerデーモンは動いた）
-sオプションでdevicemapperを指定。
```
ExecStart=/usr/bin/dockerd -s=devicemapper -H fd:// --containerd=/run/containerd/containerd.sock
```
起動
```sh
# sytemctl daemon-reload
# systemctl start docker
```
エラーなし！Dockerデーモンは動いた！

```sh
# systemctl status docker.service
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/system/docker.service.d
           └─http-proxy.conf
   Active: active (running) since 木 2023-05-11 18:05:40 JST; 19h ago
```

## dockerコマンドを実行してみたが・・・
```sh
# docker images
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
```
エラー・・・接続方式が正しくなかったらしい。

dockerコマンドはデフォルトでunixのソケットを使用するとのこと。  

参考：https://matsuand.github.io/docs.docker.jp.onthefly/engine/reference/commandline/dockerd/#daemon-socket-option

## unixソケットで待ち受けるように設定してDockerデーモンを起動するようにしてみた

-Hオプションでunix:///var/run/docker.sockを指定。
```
ExecStart=/usr/bin/dockerd -s=devicemapper -H unix:///var/run/docker.sock --containerd=/run/containerd/containerd.sock
```
再起動し、dockerコマンドを実行。
```sh
# systemctl daemon-reload
# systemctl restart docker
# docker images
REPOSITORY                          TAG       IMAGE ID       CREATED         SIZE
...
```
エラーなく動きました！

# おわりに
正しい解決策かはわかりませんが、今回Dockerのアップデートを疑い、Dockerデーモンの起動オプションを変更することでエラーを回避しました。  
dockerdの起動時のエラーに対して-s=devicemapperでストレージドライバを指定し、
dockerコマンドのエラーに対して-H unix:///var/run/docker.sockでunixソケットで待ち受けるように設定しました。  
具体的には、/lib/systemd/system/docker.service の
```
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
```
を
```
ExecStart=/usr/bin/dockerd -s=devicemapper -H unix:///var/run/docker.sock --containerd=/run/containerd/containerd.sock
```
に変更しました。  

Linuxカーネルのアップデートが原因、あるいはストレージドライバを変更する方がよい、という可能性は考えられると思っています。もし正しい解決策がある、間違っているところがある、などあればご指摘いただけると幸いです。



# 参考文献
https://github.com/moby/moby/issues/22685

https://matsuand.github.io/docs.docker.jp.onthefly/engine/reference/commandline/dockerd/#daemon-socket-option