Docker再起動後にコンテナは戻るか:restart設定4種を試した
Dockerデーモンの再起動後もコンテナを動かしておきたいなら、Composeのrestart:をunless-stoppedかalwaysにする。既定のnoでは戻らない。on-failureは止まるときの終了コードで結果が変わったので、再起動後の復帰には使わない。
2026年10月3日に、この違いをDockerデーモンの再起動で確かめた。VPSのOS更新や再起動の前に、どのコンテナが戻る設定になっているかを確かめる材料として、結果とDocker公式の説明と食い違った点を記録する。
試した環境と方法
- 環境: GitHub Actionsの実行環境(Ubuntu 24.04.5 LTS)、Docker Engine 28.0.4、Docker Compose v2.38.2。
live-restoreは無効(既定のまま) - 再起動の方法:
sudo systemctl restart docker。OSそのものは再起動していない - コンテナ:
alpine:3.20でsleepを動かすだけのもの。停止のシグナル(SIGTERM)を受けると終了コード0で終わる型(trap "exit 0" TERM)と、シグナルを無視して強制終了(終了コード137)される型の2種類を用意した
VPS上のn8nやデータベースで試した結果ではない。OSの再起動も試していない。OSの再起動では停止処理の順序や時間がデーモンの再起動と違う場合があり、特にon-failureの結果が同じになるとは限らない。
結果:設定ごとに戻ったかどうか
| restart設定 | 動いていたコンテナ | 手で止めたコンテナ(docker stop・docker compose stop) |
|---|---|---|
no(既定) |
戻らなかった(2つの型とも) | 戻らなかった(2つの型とも) |
on-failure |
終了コード137の型は戻った。0の型は戻らなかった | 終了コード137の型は戻った。0の型は戻らなかった |
always |
戻った(2つの型とも) | 戻った(2つの型とも) |
unless-stopped |
戻った(2つの型とも) | 戻らなかった(2つの型とも) |
alwaysとunless-stoppedは、動いていたものについては同じ結果だった。差が出たのは手で止めたコンテナだった。この2つの設定は、docker compose stopで止めた場合も同じ結果だった(Composeではon-failureとnoは試していない)。
起動直後に終了コード1で終わるコンテナにon-failure:3を付けた場合は、3回再起動した後に止まり、デーモンを再起動しても止まったままだった(再起動回数は3のまま)。
公式の説明と違った点:on-failure
Docker公式は、on-failureはコンテナが失敗で終了したときだけ再起動し、デーモンの再起動では再起動しないと説明している(Docker Docs: Start containers automatically)。
今回の環境では、動いていたon-failureのコンテナのうち、SIGTERMを無視して強制終了されたもの(終了コード137)が、デーモンの再起動後に起動し直した。SIGTERMで終了コード0を返したものは止まったままだった。手で止めたon-failureのコンテナも、終了コード137の型はデーモンの再起動後に起動した。公式は、手で止めたコンテナはデーモンの再起動まで再起動の設定を無視すると説明している。
デーモンの停止やdocker stopでコンテナが終わったときの終了コードを、そのまま「失敗かどうか」の判定に使った結果と見ている。Dockerのソースコードまでは確かめていない。
いずれにしても、on-failureで戻るかどうかはアプリの終了処理に左右される。同じイメージでも、版が変わって終了処理が変われば結果も変わり得る。Dockerの再起動の後に戻したいサービスにはunless-stoppedかalwaysを使う。OSの再起動では、あわせて下の「確かめる3つ」の1を確かめる。
alwaysとunless-stoppedは、止めておきたいものがあるかで選ぶ
公式の説明では、alwaysは手で止めたコンテナもデーモンの再起動時に起動し、unless-stoppedは手で止めたものを起動しない。今回の結果もこの説明どおりだった。
- 移行中の旧データベースや、調査のために止めた処理など、止めたままにしておきたいコンテナがある →
unless-stopped。Dockerが再起動したときに旧環境がalwaysで起き上がると、書き込み先が2つになるおそれがある(移行と切戻しの計画) - 手で止めたことを忘れても、再起動の後は必ず全部を動かしたい →
always
unless-stoppedを選んだら、作業で止めたコンテナを再開し忘れないよう、止めた理由と再開の担当を保守の作業票に書いておく。
設定とあわせて確かめる3つ
- Dockerデーモン自体が起動時に立ち上がるか。 Docker公式は、DebianとUbuntuでは既定で起動時に立ち上がり、それ以外のsystemdのディストリビューションでは
sudo systemctl enable docker.serviceとsudo systemctl enable containerd.serviceで有効にすると案内している(Docker Docs: Linux post-installation steps)。systemctl is-enabled dockerがenabledを返すか見る。今回の環境はenabledだった。 - 動いているコンテナに設定が入っているか。
docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' <コンテナ名>で今の値が出る。Docker公式によると、compose.yamlにrestart:を書き足してもdocker compose restartでは反映されない(公式の記述はrestartで反映される変更にまとめた)。docker compose up -dでコンテナを作り直すか、docker update --restart unless-stopped <コンテナ名>で変える。今回の環境で、docker updateの後にdocker inspectの値が変わることも確かめた。 - 戻った後に使えるか。 restart設定はコンテナを起動するだけで、データベースの準備が整うのを待ったり、処理が通るかを確かめたりはしない。起動順はComposeの起動順とhealthcheck、通知は監視と通知の検証で決める。
実行スクリプトと記録
上の表の組み合わせ(Composeの2件を除く)は、実行スクリプトにまとめて2026年10月3日にもう一度実行し、同じ結果になった。実行記録(JSON)を公開する。スクリプトはsudo systemctl restart dockerを実行し、同じホストの全コンテナが一度止まるので、止めてよい使い捨てのDocker環境だけで試す。