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 が起動しない場合の一般的な解決策

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

推薦する

JavaScript クロージャの説明

目次1. クロージャとは何ですか? 1.2 クロージャのメモ化: 関数は定義された環境を記憶する1....

Vueはel-tree遅延読み込みを使用して、追加、削除、変更、クエリ機能を実装します。

Vue のツリー表示については、プロジェクトが使用されています: エフェクト ダイアグラムがツリー...

入力選択スタイルを変更する CSS 疑似クラスのサンプルコード

注: この表はW3Schoolチュートリアルから引用したものです疑似要素の分類と機能: 入力選択スタ...

JavaScript を使用して userAgent を通じていくつかの一般的なブラウザを判別する方法

序文通常、h5 ページを作成するときは、WeChat、QQ、Weibo などのエコシステム内でトラフ...

Ubuntu での MySQL および MySQL Workbench のインストール チュートリアル

Ubuntu に jdk をインストールする: [リンク] UbuntuにEclipseをインストー...

Tomcat が https アクセスをサポートするための手順の説明

tomcat を https アクセスに対応させる方法ステップ: (1)キーストアファイルを生成する...

MySQLデータベースのSYNフラッディング問題を解決する

Syn 攻撃は、最も一般的で最も簡単に悪用される攻撃方法です。TCP プロトコルの欠陥を利用して、偽...

検証コード干渉を実装する js (動的)

この記事の例では、検証コードの動的干渉を実装するためのjsの具体的なコードを共有しています。具体的な...

MySQL チュートリアル データ定義言語 DDL の例 詳細な説明

目次1. SQL言語の基本機能の紹介2. データ定義言語の目的3. データベースの作成と破棄4. デ...

Windows Server 2008R2 ファイル サーバーを Windows Server 2016 にアップグレードする

ユーザー組織には、ドメインに参加している 2 台の Windows Server 2008 R2 フ...

Docker 経由で CentOS コンテナを作成する手順

目次序文コンテナ間の通信を容易にするためのブリッジネットワークを作成するCentOS7イメージを使用...

MySQL で binlog を使用する際のフォーマットの選択方法

目次1. binlogの3つのモード1.ステートメントレベルモード2. 行レベルモード3. 混合モー...

MYSQL の COLLATE とは何ですか?

序文MySQL で show create table <tablename> コマンド...

CSS の位​​置属性 (absolute|relative|static|fixed) の概要と応用

まず、CSS3 Api の position 属性の定義を見てみましょう。 static: 特別な配...

VueはWebSocketを使用してチャット機能をシミュレートします

この効果は、2つのブラウザが互いにシミュレートしていることを示しています 1. シミュレートされたノ...