Docker の CMD と ENTRYPOINT の違い

Isaac Tony 2023年1月30日
  1. Docker の CMD コマンド
  2. Docker の ENTRYPOINT コマンド
  3. まとめ
Docker の CMD と ENTRYPOINT の違い

さまざまな環境でのソフトウェアと依存関係の管理に関しては、Docker コンテナーが標準になっています。実際のアプリケーションで作業する場合は、アプリケーションコンテナイメージをビルドする前に、Docker ファイルを作成する必要があります。

Docker ファイルは、イメージをアセンブルするときに呼び出される一連の命令を含む、単なる読み取り専用のテキストドキュメントです。これらのコマンドには、RUNCMD、および ENTRYPOINT が含まれます。

この記事では、これらのコマンドの使用法について説明します。Docker の学習の初期段階にあると思われるほとんどの開発者は、これらのコマンドを同じ意味で使用する傾向があり、問題が発生する可能性があります。

Docker の CMD コマンド

このコマンドは、dockerRUN コマンドが実行されるたびに実行される命令を指定します。ただし、これには、引数を指定せずに dockerRUN コマンドを実行する必要があります。

引数を指定すると、このコマンドは上書きされます。一方、コマンドライン引数が指定されていない場合、CMD コマンドが実行されます。

ECHO コマンドは実行時に同じ目的を果たすために使用できるため、CMD コマンドは Docker コンテナーが正しく機能するために必須ではありません。ただし、コンテナが起動するたびに実行可能ファイルを実行する場合は、CMD コマンドが便利です。

CMD コマンドを使用して実行時に実行可能ファイルを実行する方法を示すために、メッセージを出力する単純なフラスコプログラムを使用して単純な Docker コンテナーを作成します。これは、必ずしも Python でなくても、任意の言語で複製できることに注意してください。

まず、メインアプリケーションを作成します。これは、以下に示すように単純なものにする必要があります。

from flask import Flask

app = Flask(__name__)


def hello():
    print("Hello, this is a simple Flask application")


hello()

同じフォルダ内で、コマンド touch Dockerfile を使用して Dockerfile を作成します。

Dockerfile は、ベースイメージ、作業ディレクトリ、およびインストールする必要のあるパッケージのみを指定します。

最後の行で、CMD コマンドに注意する必要があります。この場合、コンテナの起動時に CMD コマンドを使用して app.py ファイルを実行しています。

#  base image
FROM python

# Set your working directory
WORKDIR /var/www/

# Copy the necessary files
COPY ./app.py /var/www/app.py
COPY ./requirements.txt /var/www/requirements.txt

# Install the necessary packages
RUN pip install -r /var/www/requirements.txt

# Run the app
CMD python3 app.py

requirements.txt は次のように表示されます。

click==8.0.4
Flask==2.0.3
gunicorn==20.1.0
itsdangerous==2.1.0
Jinja2==3.0.3
MarkupSafe==2.1.0
Werkzeug==2.0.3

すべての準備が整ったので、Docker イメージを作成できます。その前に、プログラムが保存されているのと同じフォルダーにいることを確認する必要があります。

この例では、以下に示すように、イメージをビルドする前に、cdmy-app フォルダーに入れます。

~/my-app$ docker build -t isaactonyloi_image .

出力:

 => [internal] load build context                                                                                                          0.9s
 => => transferring context: 320B                                                                                                          0.1s
 => [2/5] WORKDIR /var/www/                                                                                                                5.1s
 => [3/5] COPY ./app.py /var/www/app.py                                                                                                    3.2s
 => [4/5] COPY ./requirements.txt /var/www/requirements.txt                                                                                3.2s
 => [5/5] RUN pip install -r /var/www/requirements.txt                                                                                    53.9s
 => exporting to image                                                                                                                     6.9s
 => => exporting layers                                                                                                                    5.8s
 => => writing image sha256:5847e4777754d9d576accd929076bfbee633ca71f049ebe1af6e9bae161f3e96                                               0.1s
 => => naming to docker.io/library/isaactonyloi_image                                                                                      0.2s
isaac@DESKTOP-HV44HT6:~/my-app$

以前の docker ファイルに基づいてイメージを正常に構築しました。以下で確認できます。

~/my-app$ docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
isaactonyloi_image   latest    5847e4777754   7 minutes ago   929MB

このイメージに基づいて dockerrun コマンドを使用して、最終的に docker コンテナーを作成できます。また、CMD コマンドを実行するための引数を渡さずにこれを行うことに注意してください。

~/my-app$ docker run isaactonyloi_image
Hello, this is a simple Flask application

これに加えて、CMD コマンドを使用すると、実行時に簡単にオーバーライドできる引数を作成することもできます。

以下の例では、CMD コマンドに変更を加えました。他のファイルはそのまま残り、新しいイメージを再構築しました。

# base image
FROM python

# Set your working directory
WORKDIR /var/www/

# Copy the necessary filesls
COPY ./app.py /var/www/app.py
COPY ./requirements.txt /var/www/requirements.txt

# Install the necessary packages
RUN pip install -r /var/www/requirements.txt

# Run the app
CMD ["echo", "Hello, Developer"]

これは、Dockerfile への変更から再構築した新しいイメージです。

~/my-app$ docker images
REPOSITORY           TAG       IMAGE ID       CREATED          SIZE
new_image            latest    73f323be0d2f   25 minutes ago   929MB

引数を渡さずに新しい Docker コンテナを再度作成すると、CMD コマンドでメッセージが表示されます。

isaac@DESKTOP-HV44HT6:~/my-app$ docker run new_image
Hello, Developer

ただし、実行時に引数を渡すと、CMD コマンドが自動的に上書きされるため、新しい引数が優先されます。したがって、以下に示すように、実行時に新しい引数を追加する柔軟性が得られます。

~/my-app$ docker run new_image hostname
da0a832888cb

上記の出力は、CMD コマンドが実行されず、新しいホスト名引数によってオーバーライドされないことを示しています。

Docker の ENTRYPOINT コマンド

docker の ENTRYPOINT コマンドは CMD コマンドと類似していますが、完全に同じというわけではありません。

CMD コマンドを使用する場合、実行時に引数を渡すことで簡単にオーバーライドできますが、ENTRYPOINT コマンドの場合はそうではありません。

したがって、ENTRYPOINT を使用して、実行時にエントリポイント命令を上書きしないようにすることができます。

以下に示すように、Dockerfile で CMD コマンドを ENTRYPOINT コマンドに置き換えるだけで、このコマンドがどのように機能するかを調べることができます。Docker ファイルへの変更に基づいて新しいイメージを作成します。

isaac@DESKTOP-HV44HT6:~/my-app$ docker build -t tonyloi_newimage .
[+] Building 42.7s (10/10) FINISHED

出力:

 => [internal] load build definition from Dockerfile                                                                                                                          2.0s
 => => transferring dockerfile: 365B                                                                                                                                          0.7s
 => [internal] load .dockerignore                                                                                                                                             1.6s
 => => transferring context: 2B                                                                                                                                               0.4s
 => [internal] load metadata for docker.io/library/python:latest                                                                                                             35.4s
 => [1/5] FROM docker.io/library/python@sha256:c90e15c86e2ebe71244a2a51bc7f094554422c159ce309a6faadb6debd5a6df0                                                               0.3s
 => [internal] load build context                                                                                                                                             1.2s
 => => transferring context: 63B                                                                                                                                              0.1s
 => CACHED [2/5] WORKDIR /var/www/                                                                                                                                            0.0s
 => CACHED [3/5] COPY ./app.py /var/www/app.py                                                                                                                                0.0s
 => CACHED [4/5] COPY ./requirements.txt /var/www/requirements.txt                                                                                                            0.0s
 => CACHED [5/5] RUN pip install -r /var/www/requirements.txt                                                                                                                 0.0s
 => exporting to image                                                                                                                                                        2.1s
 => => exporting layers                                                                                                                                                       0.0s
 => => writing image sha256:15fb8e4e3ff58ed529b11342bba75b029fd4323beb24aac70ca36b178d04cb34                                                                                  0.2s
 => => naming to docker.io/library/tonyloi_newimage                                                                                                                           0.1s
isaac@DESKTOP-HV44HT6:~/my-app$

この出力は、新しいイメージの作成に成功したことの証です。これで、このイメージに基づいて新しい Docker コンテナを作成できます。

イメージ名またはイメージ ID を使用してコンテナーを作成することを選択できます。どちらも、docker images コマンドを使用してアクセスできます。これにより、以前に作成したイメージも表示されます。

~/my-app$ docker images
REPOSITORY           TAG       IMAGE ID       CREATED          SIZE
tonyloi_newimage     latest    15fb8e4e3ff5   48 minutes ago   929MB
new_image            latest    73f323be0d2f   48 minutes ago   929MB
isaactonyloi_image   latest    5847e4777754   48 minutes ago   929MB

引数を追加せずに Docker コンテナを構築すると、次のような出力が得られるはずです。

isaac@DESKTOP-HV44HT6:~/my-app$ docker run tonyloi_newimage
Hello, Developer

このイメージに基づいて別のコンテナーを作成するときに引数を渡そうとすると、CMD コマンドの場合とは異なり、これらの新しい引数は ENTRYPOINT コマンドをオーバーライドしないことに注意してください。

これは以下で確認できます。

isaac@DESKTOP-HV44HT6:~/my-app$ docker run tonyloi_newimage Welcome to ADC
Hello, Developer Welcome to ADC

まとめ

これらの 2つのコマンドは非常に似ていると言えます。ただし、それらの違いは、CMD コマンドは実行時にオーバーライドできますが、ENTRYPOINT コマンドはオーバーライドできないことです。

また、状況によっては、2つのコマンドを同時に使用する必要がある場合があります。

著者: Isaac Tony
Isaac Tony avatar Isaac Tony avatar

Isaac Tony is a professional software developer and technical writer fascinated by Tech and productivity. He helps large technical organizations communicate their message clearly through writing.

LinkedIn

関連記事 - Docker Command