Dockerで--restart alwaysにしているのにコンテナ再起動が諦められている場合はNFSなどのディレクトリマウント漏れを疑いましょう

## それはある日のこと

**Docker には `--restart always` オプションがあり、特に指定がなければ、コンテナを何があっても無限回再起動してくれます**。サーバ上でサービスを立ち上げる際はとても頼りになるオプションです。

さて、そんな便利な `--restart always` ですが、ある日Dockerコンテナを動かしているサーバを再起動するとなぜか `--restart always` が指定されているのに **一部のコンテナの再起動が行われていないことがありました**。

それどころか、 **一度起動に失敗した後、再起動すらかけられていませんでした**。 仮に何らかの原因で起動に失敗したとしても、Dockerが無限回再起動してくれるはずでは？


## `--restart always` 指定しているのにコンテナが再起動されない原因は、ディレクトリのボリュームマウントに失敗したから

サーバのログを調査してみると、下記のようなログが出力されていました。

```
OCI runtime failed:
container_linux.go:380:
  starting container process caused:
process_linux.go:545:
  container init caused:
rootfs_linux.go:76:
  mouting \"/mnt/nfs/dir_foobar\" to rootfs at \"/app/dir_foobar\" caused ...
```

これを見てピンと来ました。 

「**そういえば、Dockerデーモン起動時にコンテナが参照しているNFSディレクトリがマウントされていないわ……**」

そうです。Dockerの **`--restart always` は** 通常時はコンテナを無限再起動してくれるものの、 **ボリュームマウント先のディレクトリが存在しなくなった場合は、一度失敗した後、再起動を行いません。**

通常の運用環境ではこういったケースに遭遇しづらいですが、一斉のOSリブートなど何らかの原因で、NFSのディレクトリがDockerコンテナ起動より遅れると、簡単に発生します。


## 再現してみる

今回の件を再現するために、下記のような定義でDockerコンテナを起動してみます。

```yml:compose.yml
services:

  a:
    image: bash
    restart: always
    volumes:
      - type: bind
        source: ./vol_a
        target: /opt/vol_a
    command: /bin/false

  b:
    image: bash
    restart: always
    volumes:
      - type: bind
        source: ./vol_b
        target: /opt/vol_b
    command: /bin/false
```

下記コマンドでコンテナが立ち上がり、その後無限に再起動が始まります。 `restart: always` なので意図した状態です。

```bash
$ mkdir vol_a vol_b
$ docker compose up -d

$ docker ps
CONTAINER ID   IMAGE     COMMAND                   CREATED         STATUS                          PORTS     NAMES
1641af0dde59   bash      "docker-entrypoint.s…"   3 minutes ago   Restarting (1) 46 seconds ago             test-a-1
b4382f5aa8cb   bash      "docker-entrypoint.s…"   3 minutes ago   Restarting (1) 45 seconds ago             test-b-1
```

この状態でコンテナ `a` にマウントしてある `vol_a` を削除してみましょう。

```bash
$ rm -r vol_a
```

再起動し続けているか起動をチェックしてみます。

```bash
$ docker ps
docker ps
CONTAINER ID   IMAGE     COMMAND                   CREATED         STATUS                          PORTS     NAMES
b4382f5aa8cb   bash      "docker-entrypoint.s…"   7 minutes ago   Restarting (1) 17 seconds ago             test-b-1
```

2つあったコンテナが、1つしかコンテナがいませんね。

 `docker ps -a` で全部のコンテナを見てみます。

```
$ docker ps -a
CONTAINER ID   IMAGE     COMMAND                   CREATED         STATUS                 
1641af0dde59   bash      "docker-entrypoint.s…"   8 minutes ago   Exited (1) 3 minutes ago                                                          test-a-1
b4382f5aa8cb   bash      "docker-entrypoint.s…"   8 minutes ago   Restarting (1) 6 seconds ago                                                      test-b-1
```

`b` のコンテナは `restart: always` によって再起動が試行され続けているのに対して、 `a`のコンテナについてはもはや再起動が試行されていないことがわかります。

`docker inspect` してみると……

```
$ docker inspect 1641af0dde59
[
    {
        "Id": "1641af0dde59442063256c610d41e49e8aedb5d1aa017555eaab23a5167a0009",
        "Created": "2023-06-28T05:22:16.53305512Z",
        "Path": "docker-entrypoint.sh",
        "Args": [
            "/bin/false"
        ],
        "State": {
            "Status": "exited",
            "Running": false,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 0,
            "ExitCode": 1,
            "Error": "failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting \"/host_mnt/Users/ssc-ksaitou/foobar/test/vol_a\" to rootfs at \"/opt/vol_a\": stat /host_mnt/Users/ssc-ksaitou/foobar/test/vol_a: no such file or directory: unknown",
            "StartedAt": "2023-06-28T05:43:40.7005604Z",
            "FinishedAt": "2023-06-28T05:43:40.701241236Z"
        },
```

エラーを見ると、ボリュームマウントするはずのものが無くて怒られているのが分かります。

```
failed to create task for container:
failed to create shim task: OCI runtime create failed:
runc create failed: unable to start container process:
error during container init:
error mounting
  \"/host_mnt/Users/ssc-ksaitou/foobar/test/vol_a\" to
    rootfs at \"/opt/vol_a\":
  stat /host_mnt/Users/ssc-ksaitou/foobar/test/vol_a: no such file or directory: unknown"
```

## まとめ

`--restart always` していても今回のようにコンテナの起動前提が満たされないと再起動試行すらされない場合があります。気をつけましょう。