Docker documentation :DockerfileにはCMD命令は1つしか存在できません。複数のCMDをリストすると、最後のCMDのみが有効になります。
CMDコマンド(私の場合はinit)の前に、単純なbashスクリプト(docker環境変数を処理する)を実行したいと思います。
これを行う方法はありますか?
必要な処理を行うカスタムエントリポイントを作成し、最後にCMDを実行します。
[〜#〜] note [〜#〜]:画像が既にカスタムエントリポイントを定義している場合、それを置き換えるのではなく拡張する必要があるか、必要な動作を変更することができます。
entrypoint.sh:
#!/bin/sh
## Do whatever you need with env vars here ...
# Hand off to the CMD
exec "$@"
Dockerfile:
COPY entrypoint.sh /entrypoint.sh
RUN chmod 755 /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
Dockerは、CMDを引数として使用して、エントリポイントを実行します。 CMDがinit
の場合:
/entrypoint.sh init
エントリポイントスクリプトの最後にあるexec
は、エントリポイントが必要な処理を終えたときにCMDに引き継ぐようにします。
ENTRYPOINTとCMDを使用すると、Dockerを初めて使用する人を混乱させることがよくあります。コメントで、あなたはそれについて混乱を表明しました。仕組みとその理由を次に示します。
ENTRYPOINTは、コンテナ内で最初に実行されるものです。引数リストとしてCMDを取ります。したがって、この例では、コンテナで実行されるのは次の引数リストです。
# ENTRYPOINT = /entrypoint.sh
# CMD = init
["/entrypoint.sh", "init"]
# or shown in a simpler form:
/entrypoint.sh init
画像にENTRYPOINTがある必要はありません。定義しない場合、Dockerにはデフォルトの/bin/sh -c
があります。
したがって、元の状況でENTRYPOINTがなく、init
のCMDを使用すると、Dockerはこれを実行します。
/bin/sh -c 'init'
^--------^ ^--^
| \------- CMD
\--------------- ENTRYPOINT
当初、DockerはCMDのみを提供し、/bin/sh -c
はENTRYPOINTとしてハードコーディングされていました(変更できませんでした)。途中のある時点で、人々はより多くのカスタム処理を行う必要があるユースケースがあり、DockerはENTRYPOINTを公開して、必要に応じて変更できるようにしました。
上記の例では、ENTRYPOINTがカスタムスクリプトに置き換えられています。 (ただし、#!/bin/sh
で始まるため、最終的にはsh
によって実行されます。)
そのENTRYPOINTは引数としてCMDを取ります。 entrypoint.shスクリプトの最後はexec "$@"
です。 $@
はスクリプトに指定された引数のリストに展開されるため、これは次のようになります。
exec "init"
そのため、スクリプトが終了すると、PID 1としてinit
に置き換えられます(これがexec
が行うこと-itreplaces別のコマンドを使用した現在のプロセス。
コメントでは、DockerfileにCMDを追加することについて尋ねました。はい、できます。
Dockerfile:
CMD ["init"]
または、コマンドにもっとある場合、例えばinit -a -b
のような引数は、次のようになります。
CMD ["init", "-a", "-b"]
ダンの答えは正しかったのですが、実装するのはかなりわかりにくいと感じました。同じ状況にある人のために、CMDではなくENTRYPOINTの使用に関する彼の説明をどのように実装したかのコード例を示します。
Dockerfileの最後の数行は次のとおりです。
#change directory where the mergeandlaunch script is located.
WORKDIR /home/connextcms
ENTRYPOINT ["./mergeandlaunch", "node", "keystone.js"]
Mergeandlaunch bashシェルスクリプトの内容は次のとおりです。
#!/bin/bash
#This script should be edited to execute any merge scripts needed to
#merge plugins and theme files before starting ConnextCMS/KeystoneJS.
echo Running mergeandlaunch script
#Execute merge scripts. Put in path to each merge script you want to run here.
cd ~/theme/rtb4/
./merge-plugin
#Launch KeystoneJS and ConnextCMS
cd ~/myCMS
exec "$@"
コードの実行方法は次のとおりです。
mergeandlaunch
シェルスクリプトを開始しますexec
コマンドに渡されます。ダンに答えてくれてありがとう。
Dockerfile内で次のようなことをしなければならなかったことがわかりました。
WORKDIR /
COPY startup.sh /
RUN chmod 755 /startup.sh
ENTRYPOINT sh /startup.sh /usr/sbin/init
注:entrypoint.shとは対照的に、スクリプトにstartup.shという名前を付けました
ここで重要なのは、「sh」を指定する必要があるということです。