Docker コンテナの正常なシャットダウン前にトラップを使用して環境のクリーンアップを実行する

Docker コンテナの正常なシャットダウン前にトラップを使用して環境のクリーンアップを実行する

実行中のコンテナが終了したときに、コンテナが完全に終了する前に環境をクリーンアップするなど、いくつかの定義済みアクションを実行するにはどうすればよいでしょうか。これはプレストップに似たフック体験です。ただし、Docker 自体はこの機能を提供することはできません。この記事では、Linux 組み込みコマンド トラップを組み合わせて、コンテナーが正常に閉じられる前にカスタム操作を実装します。

実行中のコンテナが終了したときに、コンテナが完全に終了する前に環境をクリーンアップするなど、いくつかの定義済みアクションを実行するにはどうすればよいでしょうか。これはプレストップに似たフック体験です。ただし、Docker 自体はこの機能を提供することはできません。この記事では、Linux 組み込みコマンド トラップを組み合わせて、コンテナーが正常に閉じられる前にカスタム操作を実装します。

コンテナを閉じる方法

実行中のコンテナをシャットダウンする方法は 3 つあり、いずれも docker コマンドラインによって開始されると理解しています。

  • 最初の方法はよりエレガントな方法ですdocker stop ContainerID
  • 2番目の方法はより恣意的であるようです: docker rm -f ContainerID
  • 3番目のタイプは、あまり使用されていませんdocker kill --signal=KILL ContainerID

Docker の設計者は、理由もなくコンテナをシャットダウンするための 3 つのコマンドの組み合わせを設計することはありません。どのようなシナリオで 3 つの方法を使用すべきでしょうか?

コンテナを終了するこれら 3 つの方法は、それぞれ若干異なります。これらの違いを説明する前に、コンテナとは関係ないと思われるいくつかの知識ポイント、つまり SIGNAL について触れておく必要があります。

プロセスとシグナル

ユーザーはシグナルを送信することでプロセスと通信できます。

ほぼすべての運用および保守エンジニアは、プロセスを強制終了するために次のコマンドを実行したことがあります。

キル -9 PID

このコマンドは正しいようです。プロセスを「強制終了」しましたが、なぜ「-9」なのでしょうか?

9 はシグナル SIGKILL のコードです。上記のコマンドは、実際に対応するプロセスにシグナルを送信します。このシグナルによって、プロセスが強制終了されます。

killコマンドの本当の意味は、プロセスに指定されたシグナルを送信することです。SIGKILL(9) に加えて、さまざまな他のシグナルを送信することもできます。

root@ubuntuserver:~# kill --help

kill: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... または kill -l [sigspec]

ジョブに信号を送信します。

root@ubuntuserver:~# kill -l

1) SIGHUP 2) シギント 3) シグクイット 4) シギル 5) シグトラップ

6) シガバート 7) シグバス 8) シグペ 9) シグナルキル 10) シグサー1

11) SIGSEGV 12) シグスレ2 13) シグパイプ 14) シガルム 15) シグターム

16) SIGSTKFLT 17) シグナル 18) シグナル継続 19) シグストップ 20) SIGTSTP

21) シグティン 22) シグトゥ 23) シグルグ 24) SIGXCPU 25) シグエックス

26) シグナル 27) シグプロフ 28) シグウィンチ 29) シジオ 30) シグプWR

31) シグシス 34) シグミン 35) シグマ最小+1 36) SIGRTMIN+2 37) シグナル最小値+3

38) シグマ最小+4 39) シグマ最小+5 40) シグマ最小+6 41) シグマイン+7 42) シグマ最小+8

43) シグマミン+9 44) シグナル最小値+10 45) シグマミニ+11 46) シグナル最小値+12 47) シグマミニ+13

48) シグマミニ+14 49) シグマ最小+15 50) シグマートマックス-14 51) シグマートマックス-13 52) シグマートマックス-12

53) シグマートマックス11 54) シグマートマックス10 55) シグマートマックス9 56) シグマックス8 57) シグマートマックス7

58) シグマートマックス6 59) シグマートマックス5 60) シグマートマックス4 61) シグマートマックス3 62) シグマートマックス2

63) シグマートマックス1 64) シグマックス

各信号の意味を詳しく説明するつもりはありません。私のスキルはまだそこまでには程遠いです。ここでは、私たちのトピックに関連する知識だけを取り上げ、説明します。

私たちのトピックに関連するシグナルはSIGTERMSIGKILL 2 つあります。

信号名コードそれを捕らえるか、無視するか?
シグナルターム15できる
シグナルキル9できない

SIGTERMは、 killコマンドによって送信されるデフォルトのシグナルです。ユーザーがプロセスの終了を要求すると、SIGTERM シグナルが生成されます。 SIGTERM シグナルはキャッチすることも無視することもできます。これにより、プロセスは保持されているリソースを解放し、終了する前にその状態を保存できるようになります。

SIGKILLプロセスに SIGKILL シグナルを送信すると、プロセスは直ちに終了 (KILL) します。 SIGTERM とは異なり、このシグナルはキャッチまたは無視することはできず、受信プロセスはこのシグナルを受信して​​もクリーンアップを実行してはなりません。しかし、 kill -9実行しても、必ずしもプロセスが強制終了され、リソースが解放されるとは限りません。いくつか特別なケースがあります:

  • ゾンビ プロセスは既に終了しており、親プロセスがそれを回収するのを待っているため、強制終了できません。
  • ブロックされたプロセスは、再び起動するまで終了しません。init プロセスは特別です。
  • init は処理対象ではないシグナルを受信しないため、SIGKILL を無視します。このルールには例外があります。Linux 上の init が ptrace の場合、SIGKILL を受信して​​強制終了される可能性があります。
  • 割り込み不可能なスリープ状態にあるプロセスは、SIGKILL が送信されても​​終了しない (およびそのリソースを解放しない) 場合があります。これは、一時的なソフトウェアの問題を解決するために Unix システムを再起動する必要がある数少ない状況の 1 つです。

コンテナとシグナル

コンテナの本質は、カプセル化されたプロセスのグループです。したがって、冒頭で述べた 3 つのコマンド ライン メソッドを使用して実行中のコンテナーを閉じることは、本質的には、コンテナー内のプロセスと対話してプロセスを「強制終了」するシグナルを送信するプロセスです。

  • ドッカー停止

docker stop ContainerIDを実行すると、コンテナ内のメインプロセスにSIGTERMシグナルが送信されます。猶予期間が経過すると、コンテナを完全に終了するためにSIGKILLシグナルが送信されます。

Docker マニュアルの原文は次のとおりです。

コンテナ内のメインプロセスはSIGTERMを受信し、猶予期間後にSIGKILL受信します。

  • ドッカーrm -f

docker rm -f ContainerID実行すると、コンテナ内のメイン プロセスにSIGKILLシグナルが直接送信されます。コンテナが強制終了されると、コンテナも削除されます。コンテナを削除する操作から判断すると、このコマンドは実行中のコンテナを停止するのではなく、停止したコンテナを削除するために使用されます。

  • ドッカーキル

docker kill --signal=KILL ContainerIDを実行すると、コンテナのメイン プロセスにさまざまなカスタム シグナルを送信できます。つまり、コンテナのkillコマンドです。現在のコマンドは、コンテナのメイン プロセスにSIGKILLシグナルを送信しています。

比較すると、実行中のコンテナを停止するためにdocker rm -f ContainerID使用すべきではありません。残りの 2 つの方法のうち、 docker stop ContainerID方が明らかに優れています。コンテナが最終的に強制終了されることを保証できるだけでなく、ユーザーが後でキャプチャして処理できるようにSIGTERMを提供することもできます。

さて、いよいよ本題に入りましょう。

信号をキャプチャして処理する

シグナルSIGTERMはキャッチできるシグナルです。コンテナのメイン プロセスがこの信号をキャプチャすると、事前に設計されたロジックをトリガーして、完全に終了する前にスケジュールされたタスクを完了することができます。たとえば、実行環境をクリーンアップしたり、データを保存したり、メインプロセスによって制御されていない他のプロセスを閉じたりすることができます。シナリオによっては、この要件が非常に顕著になります。

Linux には、シグナルをキャプチャし、プロセスが完全に終了する前に特定のタスクが実行されるようにする組み込みのtrapコマンドが用意されています。

root@ubuntuserver:~# トラップ --help

トラップ: トラップ [-lp] [[arg] シグナル仕様 ...]

信号やその他のイベントをトラップします。

基本的な使い方は以下のとおりです。

トラップ do_some_things SIGSPEC

アイデアは明確です。コンテナが終了する前に実行する必要があるすべての処理を完了するには、コンテナの起動スクリプトにtrap命令を追加する必要があります。

以下は、コンテナの ENTRYPOINT として実行されるスクリプトの例です。

#!/bin/bash

関数 clean_up_term {
  rm -rf /データ/tmp
  echo "clean_up_term が実行中"
}

トラップ clean_up_term SIGTERM

((i=1;i<=1000;i++)) の場合
  する
    echo "$i を待つ"
    睡眠1
  終わり 

コンテナが起動したら、別のターミナルからdocker stop ContainerIDコマンドを実行し、次の結果を確認できます。

guox@MacBook-Pro-For-Guox: /Users/guox/GitHub/test-plugin git:(master) ✗

➜ docker run -ti --name=clean -v $(pwd)/data:/data clean

1を待つ

2を待つ

3を待つ

4を待つ

5分待つ

6を待つ

7を待つ

8を待つ

9を待つ

10分待つ

11を待つ

12を待つ

13を待つ

clean_up_term 実行中

14を待つ

15分待つ

16を待つ

17を待つ

18を待つ

19を待つ

20分待つ

21を待つ

22を待つ

23を待つ

guox@MacBook-Pro-For-Guox: /Users/guox/GitHub/test-plugin git:(master) ✗

SIGTERMシグナルは実際にコンテナによってキャッチされ、関連するクリーンアップ操作が実行されます。 docker stop ContainerID猶予期間を提供するため、クリーンアップ操作が実行された後、コンテナのメインプロセスは終了する前にしばらく実行を続けます。

これで、docker コンテナが正常に終了する前に、trap を使用して環境のクリーンアップを実行する方法についての説明は終了です。docker コンテナ実行環境のクリーンアップの詳細については、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Docker はすべてのコンテナをバッチ起動して閉じます
  • Dockerコンテナを閉じずに終了する方法の詳細な説明
  • Docker クリーンアップ環境操作

<<:  中国語と英語のフォント名の比較表(FounderとArphicを含む)

>>:  CSS 動的高さ遷移アニメーション効果の実装

推薦する

JavaScript setinterval 1秒遅延ソリューション

setinterval を使用すると、ページを開いた直後に 1 秒の遅延後に実行されることがわかりま...

CSS スティッキーフッタークラシックレイアウトの実装

スティッキーフッターレイアウトとは何ですか?一般的な Web ページのレイアウトは、通常、ヘッダー部...

Linux 上の MySQL 5.7 でパスワードを忘れる問題を解決する

1. 問題Linux 上の mysql5.7 のパスワードを忘れました2. 解決策• ステップ 1:...

Bash スクリプトでの配列メソッドの作成と使用の概要

Bashで配列を定義するbash スクリプトで新しい配列を作成する方法は 2 つあります。 1 つ目...

VMware vSphere6.0 サーバー仮想化の展開とインストールの図 (詳細な手順)

1. VMware vSphere 導入の早期計画のポイント1. vSphereの利点(わずかに)...

NginxとLuaによるグレースケールリリースの実装

memcachedをインストールする yum インストール -y memcached #memcac...

Nginx gzip設定について

nginx がリソース圧縮を実現する原理は、ngx_http_gzip_module モジュールを介...

MySQL でスロークエリログ機能を有効にする方法

MySQL スロー クエリ ログは、問題のあるクエリを追跡するのに非常に役立ちます。現在のプログラム...

CSSを使用してすべての子要素を選択する方法の詳細な説明

CSS を使用してすべての子要素を再帰的に選択するにはどうすればよいですか?以下の記事では、CSS ...

Jenkins を使用した Vue プロジェクトのワンクリック パッケージングと公開の実装

目次Jenkinsのインストールインストールポート番号を変更します(デフォルトのポートは8080です...

コードブロックのハイライトをコピーして表示できる js プラグイン highlight.js + clipboard.js 統合

主に2つの側面から: 1. ハイライト/改行2. コードのコピーボタンこれら両方には既製のプラグイン...

DeepinでPyenvをインストールする手順

序文これまでは、/bin/ ディレクトリのソフトリンクを変更して Python のバージョンを切り替...

HTML要素にフォーカスを設定する方法

コードをコピーコードは次のとおりです。 <本文<フォームアクション="&quo...

Spark SQL の 4 つの一般的なデータ ソースの詳細な説明

汎用ロード/書き込みメソッドオプションを手動で指定するSpark SQL の DataFrame イ...

Tomcat のプレースホルダーによるポート設定方法 (パラメータ指定方式)

仕事で必要になったため、インターネットで多くの情報を見つけましたが、それらはすべてコピーアンドペース...