stop_timeout オプションで Docker 停止タイムアウトを柔軟に設定
kamal の停止処理は、proxy か non‑proxy のロールによってデフォルトのタイムアウトが異なります。この PR は、そのタイムアウトを明示的に制御できる stop_timeout オプションを導入し、ロール単位・全体単位で上書き可能にします。
背景
既存の停止ロジックは drain_timeout を流用しており、proxy ロールでは Docker のデフォルト 10 秒、non‑proxy ロールでは drain_timeout(デフォルト 30 秒)が適用されていました。この設計では、同一コンテナ内に proxy と non‑proxy の両方をデプロイした場合、non‑proxy ロールが 10 秒のタイムアウトで停止されるリスクがあります。
この問題を解消するために、停止時のタイムアウトを個別に設定できるオプションが必要となり、本 PR で stop_timeout が追加されました。
技術的な変更
stop_timeout の設定取得メソッドが lib/kamal/configuration.rb に追加され、raw_config.stop_timeout を返すようになりました。
@@
def drain_timeout
raw_config.drain_timeout || 30
end
+ def stop_timeout
+ raw_config.stop_timeout
+ end
設定ドキュメント (lib/kamal/configuration/docs/configuration.yml) に stop_timeout の説明が追記され、非 proxy ロールは drain_timeout、proxy ロールは 10 秒がデフォルトと明記されました。
@@
# How long to wait for a container to drain, default 30:
drain_timeout: 10
+# Stop timeout
+#
+# How long to wait for a container to stop after SIGTERM, default is
+# the drain_timeout for non-proxied roles and 10s (Docker default) for proxied roles.
+# Can be overridden per role:
+stop_timeout: 30
ロール単位でのオーバーライド例が lib/kamal/configuration/docs/role.yml に追加され、stop_timeout キーが使用できることを示しています。
@@
cmd: "bin/jobs"
+ stop_timeout: 30
options:
memory: 2g
lib/kamal/configuration/role.rb の stop_args が改修され、stop_timeout が存在すればそれを直接使用し、無ければ従来のロジック(proxy なら nil、非 proxy なら config.drain_timeout)をフォールバックします。また、ロール固有の stop_timeout を取得するヘルパー stop_timeout が追加されました。
@@
- timeout = running_proxy? ? nil : config.drain_timeout
+ timeout = stop_timeout || (running_proxy? ? nil : config.drain_timeout)
@@
def stop_args
@@
end
+
+ def stop_timeout
+ specializations["stop_timeout"] || config.stop_timeout
+ end
テストスイートにも新機能を検証するケースが加えられ、stop_timeout が正しくコマンド文字列や引数へ反映されることを確認しています(test/commands/app_test.rb、test/configuration/role_test.rb)。
設計判断
stop_timeout は グローバル設定 + ロール固有設定 の二層構造で導入され、既存の設定階層 (raw_config → specializations) と整合性を保ちました。この設計により、既存ロジックへの侵入は最小限に抑えつつ、柔軟な上書きが可能です。
デフォルト値は proxy ロールは Docker のデフォルト 10 秒、非 proxy ロールは drain_timeout とし、既存ユーザーへの影響を避けています。新たに stop_timeout を明示的に設定しない限り、従来通りの挙動が維持されます。
まとめ
stop_timeout オプションの追加により、kamal の停止処理はロール単位・全体単位で細かくチューニングできるようになりました。デフォルトは従来と同様の安全な挙動を保ちつつ、同一コンテナ内での proxy / non‑proxy 混在環境でも適切なタイムアウトを設定できる点が大きな利点です。