それはある日のこと
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コンテナを起動してみます。
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
なので意図した状態です。
$ 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
を削除してみましょう。
$ rm -r vol_a
再起動し続けているか起動をチェックしてみます。
$ 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
していても今回のようにコンテナの起動前提が満たされないと再起動試行すらされない場合があります。気をつけましょう。