はじめに
Docker コンテナは、様々なアプリケーションやサービスを実行するために広く使用されていますが、長時間実行されるコンテナのライフサイクルを管理することは難しい場合があります。このチュートリアルでは、長時間実行される Docker コンテナを適切にシャットダウンするプロセスを案内し、スムーズな移行を確保し、潜在的なデータ損失やアプリケーションの問題を防ぎます。
Docker コンテナのライフサイクルの理解
開発者がアプリケーションを効果的に管理するためには、Docker コンテナの明確に定義されたライフサイクルを理解する必要があります。このセクションでは、Docker コンテナのライフサイクルの概要を説明します。これには、コンテナが遷移するさまざまな状態と、このライフサイクルの基礎となる主要な概念が含まれます。
Docker コンテナの状態
Docker コンテナは、そのライフタイム中にいくつかの異なる状態で存在することができます。
- Created(作成済み): コンテナが作成されたが、まだ起動されていない状態です。
- Running(実行中): コンテナが現在、メインプロセスを実行している状態です。
- Paused(一時停止中): コンテナのメインプロセスが一時停止されているが、コンテナはまだ実行中です。
- Stopped(停止済み): コンテナのメインプロセスが停止されている状態です。
- Restarting(再起動中): コンテナが現在、再起動中です。
- Exited(終了済み): コンテナが停止し、メインプロセスが終了している状態です。
これらの状態を理解することは重要です。なぜなら、これらの状態によって、コンテナに対して実行できるアクションと期待できる動作が決まるからです。
graph LR
Created --> Running
Running --> Paused
Paused --> Running
Running --> Stopped
Stopped --> Running
Stopped --> Exited
Docker コンテナのライフサイクルイベント
コンテナの状態に加えて、Docker コンテナのライフサイクル中にいくつかの重要なイベントが発生します。
- Create(作成): 新しいコンテナが作成されます。
- Start(起動): コンテナのメインプロセスが起動されます。
- Stop(停止): コンテナのメインプロセスが停止されます。
- Restart(再起動): コンテナが手動または自動で再起動されます。
- Pause/Unpause(一時停止/再開): コンテナのメインプロセスが一時停止または再開されます。
- Kill(強制終了): コンテナのメインプロセスが強制的に終了されます。
- Delete(削除): コンテナがシステムから削除されます。
これらのライフサイクルイベントを理解することは、Docker コンテナの動作を管理および自動化するために不可欠です。
Docker CLI を使用したコンテナのライフサイクルの管理
Docker CLI は、コンテナのライフサイクルとやり取りするためのいくつかのコマンドを提供しています。
docker create: 新しいコンテナを作成します。docker start: 停止しているコンテナを起動します。docker stop: 実行中のコンテナを停止します。docker restart: コンテナを再起動します。docker pause: 実行中のコンテナを一時停止します。docker unpause: 一時停止しているコンテナを再開します。docker kill: 実行中のコンテナを強制的に停止します。docker rm: コンテナを削除します。
これらのコマンドを使用すると、Docker コンテナのライフサイクルをプログラムで管理し、コンテナ管理に関連するさまざまなタスクを自動化することができます。
長時間実行されるコンテナを適切に停止する
長時間実行される Docker コンテナを扱う際には、コンテナが適切に停止されるようにすることが重要です。つまり、コンテナが終了する前に、コンテナのメインプロセスが必要なクリーンアップやシャットダウンタスクを実行できるようにする必要があります。このセクションでは、長時間実行される Docker コンテナを適切に停止するための戦略を探ります。
SIGTERM シグナルの理解
Docker コンテナを適切に停止するための主なメカニズムは、コンテナのメインプロセスにSIGTERMシグナルを送信することです。このシグナルは、プロセスにシャットダウンプロセスを開始し、必要なクリーンアップタスクを実行するよう通知します。
デフォルトでは、docker stopコマンドを実行すると、Docker はコンテナのメインプロセスにSIGTERMシグナルを送信し、プロセスが終了するまでデフォルトのタイムアウト期間(通常は 10 秒)待機します。タイムアウト期間内にプロセスが終了しない場合、Docker はSIGKILLシグナルを送信し、プロセスを強制的に終了させます。
シャットダウン動作のカスタマイズ
長時間実行される Docker コンテナのシャットダウン動作をカスタマイズするには、以下のオプションを使用できます。
--stop-signal:docker stopコマンド実行時に、コンテナのメインプロセスに送信する代替シグナルを指定します。例えば、--stop-signal=SIGINTとすると、デフォルトのSIGTERMではなくSIGINTシグナルが送信されます。--stop-timeout:SIGKILLシグナルを送信する前に、コンテナのメインプロセスが終了するのを待つ秒数を指定します。例えば、--stop-timeout=30とすると、プロセスが強制終了される前に 30 秒間終了するのを待ちます。
以下は、長時間実行されるコンテナを起動する際にこれらのオプションを使用する例です。
docker run -d --name my-app --stop-signal=SIGINT --stop-timeout=60 my-app:latest
このコマンドは、my-appという名前の長時間実行されるコンテナを起動します。docker stopコマンドが発行されると、コンテナのメインプロセスにSIGINTシグナルが送信され、SIGKILLシグナルを送信する前に最大 60 秒間終了するのを待ちます。
アプリケーションで適切なシャットダウンを実装する
長時間実行される Docker コンテナが適切に停止されるようにするには、アプリケーションを設計してSIGTERM(または代替)シグナルを処理し、終了する前に必要なクリーンアップタスクを実行するようにすることが重要です。これには以下のようなタスクが含まれる場合があります。
- メモリ内のデータを永続的なストレージに保存する
- ネットワーク接続やデータベース接続を閉じる
- ログやその他の出力をフラッシュする
- その他のアプリケーション固有のクリーンアップタスクを実行する
アプリケーションでこのシグナルハンドリングを実装することで、コンテナを制御された予測可能な方法で停止させ、データ損失やその他の問題のリスクを最小限に抑えることができます。
適切なシャットダウンのための戦略
長時間実行される Docker コンテナを適切にシャットダウンするには、スムーズで制御可能なシャットダウンプロセスを確保するためのいくつかの戦略を採用できます。このセクションでは、適切なシャットダウンのための主要な戦略とベストプラクティスのいくつかを探ります。
アプリケーションでのシグナルハンドリング
適切なシャットダウンのための最も重要な戦略の 1 つは、アプリケーションでシグナルハンドリングを実装することです。これには、SIGTERM(または代替)シグナルを待ち受け、アプリケーションが終了する前に必要なクリーンアップタスクを実行するコードを記述することが含まれます。
以下は、Node.js アプリケーションでシグナルハンドリングを実装する方法の例です。
process.on("SIGTERM", () => {
console.log("Received SIGTERM signal, starting graceful shutdown...");
// Perform cleanup tasks, such as:
// - Saving in-memory data to persistent storage
// - Closing network connections or database connections
// - Flushing logs or other output
// - Performing any other application-specific cleanup tasks
console.log("Graceful shutdown complete, exiting process.");
process.exit(0);
});
このシグナルハンドリングを実装することで、アプリケーションは制御されたシャットダウンを実行し、データ損失やその他の問題のリスクを最小限に抑えることができます。
ヘルスチェックと生存プローブの使用
適切なシャットダウンのもう 1 つの戦略は、Docker の組み込みのヘルスチェックと生存プローブ機能を使用することです。これらの機能を使用すると、Docker がコンテナの健全性と準備状態を判断するために使用できるチェックを定義できます。
シャットダウンプロセス中に、これらのプローブを使用して、コンテナがシャットダウン中であることを Docker に通知し、コンテナを削除する前にシャットダウンが完了するのを待機させることができます。
以下は、Docker コンテナでヘルスチェックと生存プローブを構成する方法の例です。
## Dockerfile
FROM node:14-alpine
COPY. /app
WORKDIR /app
CMD ["node", "server.js"]
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -f http://localhost:3000/healthz || exit 1
LABEL com.labex.shutdown.signal=SIGINT
LABEL com.labex.shutdown.timeout=60
この例では、HEALTHCHECK命令は、コンテナの Web サーバーの/healthzエンドポイントをチェックするヘルスチェックを定義しています。LABEL命令は、適切なシャットダウンに使用するシグナル (SIGINT) とタイムアウト期間 (60 秒) を定義しています。
シャットダウンプロセス中に、アプリケーションはヘルスチェックエンドポイントを更新して、シャットダウンが進行中であることを通知し、コンテナを削除する前にシャットダウンが完了するのを Docker に待機させることができます。
オーケストレーションフレームワークの活用
Kubernetes や Docker Swarm などのオーケストレーションフレームワークで Docker コンテナを実行している場合、これらのフレームワークの組み込み機能を活用して適切なシャットダウンを支援できます。
たとえば、Kubernetes では、preStopフックを使用して、コンテナが終了する前にクリーンアップタスクを実行するコマンドまたはスクリプトを実行できます。また、terminationGracePeriodSecondsフィールドを使用して、コンテナが適切にシャットダウンするために与えられる時間を指定できます。
以下は、preStopフックと適切な終了期間を設定した Kubernetes デプロイメントを構成する方法の例です。
## kubernetes-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:latest
ports:
- containerPort: 3000
lifecycle:
preStop:
exec:
command: ["/app/shutdown.sh"]
terminationGracePeriodSeconds: 60
この例では、preStopフックは、コンテナが終了する前に必要なクリーンアップタスクを実行するスクリプト (/app/shutdown.sh) を実行します。terminationGracePeriodSecondsフィールドは、コンテナが強制終了される前に 60 秒間適切にシャットダウンする時間を与えます。
これらのオーケストレーションフレームワークの機能を活用することで、コンテナのシャットダウンプロセスの信頼性と予測可能性をさらに向上させることができます。
まとめ
このチュートリアルでは、Docker コンテナのライフサイクルを理解することの重要性と、長時間実行されるコンテナを適切にシャットダウンするための戦略を学びました。概説されたベストプラクティスに従うことで、スムーズで信頼性の高いシャットダウンプロセスを確保し、データ損失やアプリケーションの中断のリスクを最小限に抑えることができます。適切なコンテナのシャットダウンの技術を習得することは、すべての Docker 開発者や管理者にとって重要なスキルです。



