Dockerfile における ENTRYPOINT と CMD の違い

Dockerfile における ENTRYPOINT と CMD の違い

Docker システムの学習チュートリアルでは、Dockerfile を使用して Docker イメージを構築するのが標準的な方法であることを学びました。Dockerfile によると、イメージにインストールされているコンポーネントの詳細を理解することができます。

Dockerfile は通常、4 つの部分で構成されます。1 つ目は、構築するベース イメージ、2 つ目はイメージ ビルダーの情報、3 つ目はイメージ構築プロセス中にイメージ レイヤーを追加するための指示、4 つ目はイメージによってコンテナーが起動されたときに実行されるプログラムです。

この記事で取り上げる ENTRYPOINT と CMD は、Dockerfile の最後の部分に属します。これら 2 つの Dockerfile 命令は、イメージの起動時に Docker バックグラウンド プログラムに実行を指示するために使用されます。この 2 つには微妙な違いがあります。

以下では、これら 2 つの命令の類似点と相違点、およびこれら 2 つを併用する高度なテクニックの観点から、2 つの命令について詳しく説明します。

CMDコマンド

CMD 命令は、コンテナの起動時に実行されるプログラムを指定します。一般的に、コンテナを起動する最も簡単な方法は、docker run を使用して docker コマンドにパラメータを渡すことです。

docker run -it イメージ /bin/bash

最後の /bin/bash は、実際にはコンテナの起動時にシェルを実行するように指示するパラメータを渡します。このプロセスはCMDコマンドで同等に置き換えることができます。

コマンド ['/bin/bash']

そのため、Dockerfile 内に CMD 命令で指定したコマンドが存在する場合は、パラメータを渡さずにコンテナを起動することができます。

docker run -it イメージ

実行効果は一貫しています。

[root@MiWiFi-R3L-srv テスト]# docker run --name test -it test_image

[ルート@3a1bb0c9e35c /]#

Dockerfile でコンテナの起動時に実行するプログラムが指定されていて、docker run でコンテナを起動するときにコマンドライン パラメータが使用されている場合、Dockerfile 内の cmd 命令は無効になります。

docker run -it イメージ /bin/ps

コンテナを起動した後にシェルが存在せず、現在のコンテナ内のプロセスステータスのみが出力され、cmd 命令の効果が上書きされることがわかります。

 PID TTY 時間 コマンド
  1 ? 00:00:00 ps
[root@MiWiFi-R3L-srv テスト]#

この時点で、cmd 効果がカバーされていることがわかります。 Dockerfile では、最後の cmd 命令のみが有効であるため、Dockerfile には 1 つの cmd 命令のみを記述する必要があります。

ENTRYPOINT命令

ENTRYPOINT 命令の効果は CMD の効果と非常に似ているため、両者の機能を混同しやすいです。最も大きな違いは使用方法にあります。ENTRYPOINT で指定したコマンドは、コンテナを起動するために docker run コマンドで使用する必要があります。docker run 命令に続く内容は、ENTRYPOINT 命令で指定した実行コマンドのパラメータとして使用されます。ENTRYPOINT で指定した linux コマンドは、通常は上書きされません。

nginxイメージを例に挙げる

まず、nginx イメージをビルドし、コンテナの実行時に実行されるプログラムとして nginx を指定します。

Centosより
MAINTAINERアロケータ
yum install -y nginxを実行します
実行 echo 'hello world' > /usr/share/nginx/html/index.html
エクスポーズ80
エントリポイント ["/usr/sbin/nginx"]

次にミラーを起動します

docker run --name test -p 5000:80 -it test_nginx -g "デーモンオフ"

最後の 2 つは、nginx の起動プログラムにパラメータとして渡されて実行されます。このとき、nginx はフォアグラウンド プログラムとして実行され、Web サーバーになります。外部にバインドされたポートに応じて、ブラウザーを通じて hello world を正常に表示できます。

両方を一緒に使用するためのヒント

2 つの違いを理解したら、それぞれの特性を利用して、デフォルトのスタートアップ プログラムを含み、docker run の起動時にスタートアップ プログラムのパラメーターを手動で指定できるイメージを構築できます。

例えば。 ENTRYPOINT を使用して nginx プログラムの起動を指定し、ヘルプ情報を表示するためのデフォルトの実行パラメータを指定します。dockerfile は次のように構成されます。

エントリポイント ["/usr/sbin/nginx"]

コマンド ["-h"]

パラメータを渡さずに docker run --name test -it test_nginx を使用すると、コンテナの起動時に cmd 命令の後のコマンドがデフォルトのパラメータとして使用され、nginx のヘルプ情報が出力されます。このとき、cmd 以降の内容は完全なコマンドではなく、パラメータです。その内容が完全なコマンドである場合、ENTRYPOINT の内容が上書きされます。

docker run --name test -it test_nginx -g "daemon off" で起動すると、指定された実行パラメータがCMD命令に対応する内容を上書きします。このとき、nginxはフォアグラウンドプロセスとして実行され、Webサーバーとして使用されます。ブラウザからHello Worldを見ることができます。

追加知識: docker-entrypoint.sh エントリファイルの作成に関するヒント

公式の Docker レジストリ (store.docker.com) では、人気のあるサードパーティ アプリケーションが各ページに Dockerfile へのリンクを提供しています。多くの Dockerfile には、次のように記述された ENTRYPOINT コマンドがあります ["docker-entrypoint.sh"]

この記事ではdocker-entrypoint.shの特別な使い方と設計ロジックを紹介します。

マイグレーション

セット-e

作成するすべてのスクリプトは、set -e で始まる必要があります。これは、いずれかのステートメントが true 以外の値に評価された場合に bash を終了するように指示します。これにより、エラーが雪だるま式に大きくなり、以前に処理されるべき致命的なエラーになるのを防ぐことができます。読みやすさを向上させるには、set -e と同じことを行う set -o errexit を使用します。

-o パイプフェイルを設定する

設計目的は上記と同じです。つまり、実行エラーが発生したらすぐに終了し、それ以上実行しないようにします。 -o pipefail のスコープはパイプラインです。つまり、Linux スクリプトでは、前のコマンドの実行に失敗した場合は、すぐに終了する必要があります。

shopt -s ヌルグロブ

Linux で * ? などのワイルドカードを使用する場合、一致するファイルがない場合、「そのようなファイルまたはディレクトリはありません」というメッセージは表示されず、コマンドの後のパラメータが削除されて実行されます。

[ “${1:0:1}” = '-' ]; の場合…

これは判断文です。公式文書では、前の行はコメントアウトされています。コマンドがオプションで始まる場合は、mysqldを先頭に追加します。

判定ステートメントは${1:0:1}で、$1(スクリプト呼び出しの最初のパラメータ)、オフセット0(オフセットなし)、文字の取得(文字列の長さの取得)を判定することを意味します。

スクリプトに続くパラメータの最初の文字がハイフンの場合、後続のすべての文字列は mysqld 起動パラメータと見なされます。

上記の操作はPythonの文字列スライスに似ています

–mysqld に「$@」を設定します

最初のパラメータが - で始まると判断された後、set -- mysqld "$@" コマンドが実行されます。set -- 構文が使用されます。set -- は、スペースで区切られたすべての文字列を $1、$2、および $3 変数に順番に格納します。新しい $@ は、set -- の後の内容全体です。

例えば: bash docker-entrypoint.sh -f xxx.conf

この場合、set --mysqld "$@"の$@の値は-f xxx.confです。

コマンド set --mysqld "$@" を実行した後:

$1 = mysqld
$2=-f
$3=xxx.conf
$@=mysqld -f xxx.conf

docker-entrypoint.sh スクリプトを -x パラメータを追加して実行すると、$@ の値が変わることがわかります。元の $@ の値に基づいて、mysqld コマンドが先頭に事前追加されます。

実行 “$@”

docker-entrypoint.sh スクリプトのほぼすべての最後の行で、exec "$@" コマンドが実行されます。

このコマンドの重要性は、イメージに対して予想される呼び出しシナリオを予測していることです。実際にイメージを使用するユーザーが、予期しない実行可能コマンドを実行すると、スクリプトの最後の行に移動して、ユーザーの新しい実行可能コマンドが実行されます。

状況評価

スクリプトの最後の行は、上記に直接言及されています。前のスクリプトでは、独自のスクリプトが呼び出される可能性がある状況を十分に考慮する必要があります。公式の MySQL dockerfile を例に挙げてみましょう。次の状況が決定されます。

-で始まる場合はパラメータとして扱われます

名前はmysqldで始まり、ユーザーIDは0(ルートユーザー)です。

mysqldが先頭にある場合

アプリケーションのすべての呼び出し形式を決定したら、最後にexec "$@"コマンドを追加する必要があります。

${mysql[@]}

シェル内の配列、${mysql[@]}を直接実行すると、この配列は実行可能プログラムとして実行されます。

➜ /tmp mysql=(mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" )
➜ /tmp echo ${mysql[1]}
マイスク
➜ /tmp echo ${mysql[2]}
--protocol=ソケット
➜ /tmp echo ${mysql[3]}
-uroot
➜ /tmp echo ${mysql[4]}
-hローカルホスト
➜ /tmp エコー ${mysql[@]}
mysql --protocol=ソケット -uroot -hlocalhost --socket=
gosu mysql を実行 “$BASH_SOURCE” “$@”

ここでのgosuコマンドは、Linuxのsudoコマンドの軽量な「代替」です。

gosu は、シェルの sudo コマンドを置き換えるために使用される、golang 言語で開発されたツールです。su コマンドと sudo コマンドにはいくつかの欠陥があり、主に TTY が不確実で、シグナル転送に問題があります。特定のユーザーでプログラムを実行したいだけの場合、su または sudo を使用すると重すぎるため、gosu が生まれました。

gosu は、コンテナ内でアプリケーションを起動するために libcontainer の原理を直接借用し、/etc/passwd を使用してアプリケーションを処理します。gosu は最初に指定されたユーザーまたはユーザー グループを見つけ、次にそのユーザーまたはユーザー グループに切り替えます。次に、exec を使用してアプリケーションを起動します。ここまでで、gosu は作業を完了しており、アプリケーションの後続の宣言サイクルには参加しません。この方法は、gosu が TTY を処理してセマフォを転送するという問題を回避し、これら 2 つのタスクをアプリケーションに直接渡して完了させます。

Dockerfile の ENTRYPOINT と CMD の違いについての説明は以上です。エディターが皆さんにお伝えする内容は以上です。参考になれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • 非ルートユーザーを使用してDockerコンテナでスクリプト操作を実行する
  • Docker ファイルの保存パス、コンテナの起動コマンド操作の取得
  • docker CMD/ENTRYPOINT が sh スクリプトを実行する問題の解決策: not found/run.sh:

<<:  Windows システムで MySQL が起動しない場合の一般的な解決策

>>:  ウェブテーブルフレームを作成するためのヒント

推薦する

mysql のインデックスと FROM_UNIXTIME に関する問題

ゼロ、背景今週の木曜日にたくさんのアラートを受け取りました。DBA に確認を依頼したところ、遅いクエ...

Nginx リバース プロキシ springboot jar パッケージ プロセス分析

Springboot プロジェクトをサーバーにデプロイする方法としては、war パッケージにパッケー...

ウェブテーブルフレームを作成するためのヒント

<br />Web テーブル フレームを作成するためのヒント。 ------------...

JavaScript関数におけるこのポイントの問題の詳細な説明

このキーワードどのオブジェクトが関数を呼び出しますか? また、関数内の this はどのオブジェクト...

MySQL 8.0 オンライン DDL クイック列追加の概要

目次問題の説明MySQLオンラインDDLで列を追加する従来の方法01 コピー方法02 インプレースメ...

要素の高さを下から上へ、上から下へ制御する CSS メソッド

よくある質問から議論を始めましょう。CSS を使用して要素の高さを [ブラウザ コンテンツ ウィンド...

CentOS8.1 で Gitlab サーバーを構築するための詳細なチュートリアル

Gitlab と Github の違いについては、あまり説明する必要はありません。一言でまとめると、...

https ウェブサイトを展開し、Nginx でアドレス書き換えを構成するための詳細な手順

Nginx は、高性能な Web サイト サーバーおよびリバース プロキシ サーバーであり、IMAP...

MySQL のストレージ エンジンの違いと比較

MyISAM ストレージエンジンMyISAM は ISAM ストレージ エンジンに基づいており、それ...

WEBAPP開発スキルのまとめ(モバイルWebサイト開発の注意点)

1. レスポンシブな Web を開発するには、ページを画面サイズに適応させる必要があります。前の記...

Vue はカスタム「モーダル ポップアップ ウィンドウ」コンポーネントのサンプル コードを実装します

目次序文レンダリングサンプルコード要約する序文ダイアログ ボックスは非常に一般的なコンポーネントであ...

Vue パッケージ化後の空白ページの解決策

1. vue-cli がプロジェクト パッケージを作成した後にページが空白になる問題の解決方法コマン...

MySQL 5.5.27 インストール グラフィック チュートリアル

1. MYSQLのインストール1. ダウンロードしたMySQLインストールファイルmysql-5.5...

MySQL で二重引用符の位置が誤っていたために起きた殺人事件の詳細な分析

1. はじめに最近、開発者が誤ってデータを削除したり更新したりするケースがよくあります。今回もまた問...

HTML ページ共通スタイル (推奨)

以下のように表示されます。 XML/HTML コードコンテンツをクリップボードにコピーbody、di...