Fargateで「STOP SIGNAL」が使えるようになりました
Dockerfileで定義されている STOPSIGNAL 命令を、 Fargate がコンテナに送るようになりました。
何が嬉しいのか?今までの課題
今まで ECS Fargateでは、graceful shutdown を実現する際に SIGTERM を受けてから安全に停止する処理を作成する必要がありました。
https://aws.amazon.com/jp/blogs/news/graceful-shutdowns-with-ecs/
しかし、ミドルウェアは停止命令による挙動が決まっています。
例えば、nginx はSIGTERMを受けるとすぐに停止します。そのため、SIGTERMを受けてSIGQUITを投げ直す trap 処理を書くなどの工夫が必要でした。
https://linuxjm.sourceforge.io/html/nginx/man8/nginx.8.html
改善された点
OCI標準に準拠するように、Dockerfile に STOPSIGNAL 任意のシグナル を指定するだけでFargate、Kubernetes、ローカルDockerのどこでも graceful shutdown が保証されるため可搬性が高まります。
なぜ今までできなかったのか?(考察)
Fargateは、AWSが管理する独自のホストOS(マイクロVM/Firecracker)上で動作していると思われるため、柔軟にアクセスできなかったのではないでしょうか。誰か詳しい人教えてください。
試してみた
検証用のソースはこちらにあります
https://github.com/nidcode/ecs-stop-signal-sample
以下のようなシンプルなプログラムを作成してテストしてみました。
const express = require('express');
const app = express();
const PORT = process.env.PORT || 8080;
const SHUTDOWN_DELAY_MS = parseInt(process.env.SHUTDOWN_DELAY_MS, 10) || 10000;
app.get('/', (req, res) => {
res.send('Running and waiting for stop signal...');
});
const server = app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
// --- シグナルハンドラ定義 ---
// SIGTERM (デフォルトの停止シグナル) 用のハンドラ
process.on('SIGTERM', () => {
handleShutdown('SIGTERM');
});
// SIGINT (カスタム検証用シグナル) 用のハンドラ
process.on('SIGINT', () => {
handleShutdown('SIGINT');
});
// SIGKILL (強制終了) は捕捉できません!
function handleShutdown(signal) {
console.log(`[${signal} RECEIVED] Graceful shutdown initiated.`);
// 1. サーバーの新しい接続受付を停止
server.close(() => {
console.log('HTTP server closed.');
});
// 2. ログの書き出しやDBクローズなどのクリーンアップ処理をシミュレート
console.log(`Starting cleanup. Waiting for ${SHUTDOWN_DELAY_MS / 1000} seconds...`);
// 猶予時間内に処理を終えることを想定
setTimeout(() => {
console.log(`[${signal} SUCCESS] Cleanup complete. Exiting cleanly.`);
process.exit(0);
}, SHUTDOWN_DELAY_MS);
}
テスト用アプリケーションの動作
- SIGINT を受け取ると10秒間クリーンアップ
- CloudWatch Logsには [SIGINT RECEIVED] のログが記録される
検証するにあたって、ECSタスク定義 stopTimeout を 15秒 に設定しました
STOPSIGNALなしの動作
server.js に適当にコメントなどを追加して差分を作成し、 cdk deploy を実施して強制的にタスクを再作成してみます
STOPSIGNALを設定
DockerfileにSTOPSIGNALを書くだけでOKです
server.jsと合わせて SIGINT を設定してみましょう
FROM node:22-slim
...
STOPSIGNAL SIGINT
CMD ["node", "server.js"]
無事にデプロイされたら、先ほどと同様に再度 cdk deploy をして強制的にタスクを作り直してみましょう。
まとめ
今回のカスタム停止シグナルサポートは、単なるパラメータの追加ではなく、AWS Fargateがコンテナランタイムの国際標準(OCI)に完全に準拠したことを示します。
これにより、コンテナ運用者は、他の環境で使っていた標準イメージをそのままFargateに持ち込めるようになり、デプロイや運用時の品質(Graceful Shutdown)が大幅に向上しました。

