それぞれの役割が分からないとどちらを使えばいいか迷ってしまうため、それぞれの使い方について解説します。
CMD
CMD は起動コマンド自体を実行することが目的でない場合に使います。例えば、Alpine Linux のイメージは何か特定のコマンドを実行する目的のイメージではないため、デフォルトのコマンドを CMD で定義しています。
https://github.com/gliderlabs/docker-alpine/blob/master/versions/library-3.8/x86_64/Dockerfile
これにより、docker run で実行する時に起動コマンド自体を上書きすることができます。
以下のようにすると、指定されたコマンドと引数がコンテナ起動時に実行されます。
docker run alpine {上書きするコマンドと引数}
ENTRYPOINT
ENTRYPOINT は起動コマンド自体を実行することが目的の場合に使います。例えば、registry のイメージは Docker のレジストリを起動することが目的のイメージのため、起動するためのコマンドが ENTRYPOINT として定義されています。
https://github.com/docker/distribution-library-image/blob/master/Dockerfile
この時、CMD をセットで記述するとコマンドの引数として用いられます。
registry の場合は、コマンド( /entrypoint.sh ) は変えずに設定ファイル ( /etc/docker/registry/config.yml ) を別のファイルに変更することができるようになっています。
以下のようにすると、指定した設定ファイルでレジストリを起動することができます。
docker run registry {設定ファイル}
まとめ
- 何らかのプログラムの実行を目的としたイメージを作成する場合は ENTRYPOINT に実行するコマンドを記述する
引数がある場合はさらに CMD でデフォルト引数を定義する - 特定のコマンドの実行を目的としないイメージを作成する場合は CMD にデフォルトで実行するコマンドを記述する