私のnodejsプロジェクトには次のファイルがあります
FROM node:boron
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install
# Bundle app source
COPY . /usr/src/app
# Replace with env variable
RUN envsubs < fil1 > file2
EXPOSE 8080
CMD [ "npm", "start" ]
環境変数を提供する-eフラグでdockerコンテナーを実行します
しかし、私は交換を見ません。 env変数が使用可能な場合、Run ccommandは実行されますか?
Dockerfileは、イメージのビルドプロセスを定義します。一度構築されると、イメージは不変です(変更できません)。ランタイム変数は、この不変のイメージに焼き付けられるものではありません。したがって、Dockerfileはこれに対処するのに間違った場所です。
おそらくやりたいことは、デフォルトのENTRYPOINT
を独自のスクリプトでオーバーライドし、そのスクリプトに環境変数で何かをさせることです。エントリポイントスクリプトは実行時(コンテナの起動時)に実行されるため、これが環境変数を収集し、それらで何かを行うのに適切なタイミングです。
最初に、エントリーポイントスクリプトについて知るためにDockerfileを調整する必要があります。 Dockerfileは環境変数の処理に直接関与していませんが、スクリプトは画像に焼き付けられるため、このスクリプトについてはまだ知る必要があります。
Dockerfile:
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["npm", "start"]
ここで、必要なセットアップを行うエントリポイントスクリプトを記述しますbeforeコマンドが実行され、最後にexec
コマンド自体が実行されます。
entrypoint.sh:
#!/bin/sh
# Where $ENVSUBS is whatever command you are looking to run
$ENVSUBS < fil1 > file2
npm install
# This will exec the CMD from your Dockerfile, i.e. "npm start"
exec "$@"
あなたがコメントでこれについて尋ねたので、ここにnpm install
を含めました。これはnpm install
実行ごとにを実行することに注意してください。それが適切な場合は問題ありませんが、毎回実行されるため、起動時間に多少の遅延が発生することを指摘したいと思います。
次に、イメージを再構築します。これにより、エントリポイントスクリプトがその一部になります。
エントリポイントスクリプトは環境変数の使用方法を知っていますが、実行時に変数をインポートするようにDockerに指示する必要があります。これを行うには、-e
フラグをdocker run
に使用できます。
docker run -e "ENVSUBS=$ENVSUBS" <image_name>
ここでは、Dockerは環境変数ENVSUBS
を定義するように指示され、割り当てられる値は現在のシェル環境からの$ENVSUBS
の値です。
これについて少し詳しく説明します。コメントでは、これがどのように組み合わされるかについて少し霧がかかっているように見えたからです。
Dockerがコンテナを起動すると、コンテナ内で1つのコマンドを実行します。このコマンドは、典型的なLinuxシステムのinit
またはsystemd
と同様にPID 1になります。このプロセスは、コンテナに必要な他のプロセスの実行を担当します。
デフォルトでは、ENTRYPOINT
は/bin/sh -c
です。 Dockerfile、docker-compose.yml、またはdockerコマンドを使用してオーバーライドできます。
コンテナーが開始されると、Dockerはentrypointコマンドを実行し、コマンド(CMD
)を引数リストとして渡します。前に、独自のENTRYPOINT
を/entrypoint.sh
として定義しました。つまり、あなたの場合、これはDockerが起動時にコンテナで実行するものです:
/entrypoint.sh npm start
["npm", "start"]
がコマンドとして定義されたため、それが引数リストとしてエントリポイントスクリプトに渡されます。
-e
フラグを使用して環境変数を定義したため、このエントリポイントスクリプト(およびその子)はその環境変数にアクセスできます。
エントリポイントスクリプトの最後で、exec "$@"
を実行します。 $@
はスクリプトに渡される引数リストに展開されるため、これは実行されます
exec npm start
また、exec
は引数をコマンドとして実行するため、replacing現在のプロセスをそれ自体と置き換えます。完了したら、npm start
はコンテナ内のPID 1になります。
コメントでは、複数のCMD
エントリを定義して複数のことを実行できるかどうかを尋ねました。
定義できるENTRYPOINT
とCMD
はそれぞれ1つのみです。これらは、ビルドプロセス中にはまったく使用されません。 RUN
やCOPY
とは異なり、これらはビルド中に実行されません。これらは、作成された画像にメタデータアイテムとして追加されます。
これらのメタデータフィールドが読み取られ、コンテナを起動するために使用されるのは、イメージがコンテナとして実行された後でのみです。
前述のように、エントリポイントは実際に実行されるものであり、CMD
が引数リストとして渡されます。それらが分離している理由は部分的に歴史的です。 Dockerの初期のバージョンでは、CMD
のみが利用可能なオプションであり、ENTRYPOINT
は/bin/sh -c
として修正されました。しかし、このような状況のため、Dockerは最終的にENTRYPOINT
をユーザーが定義できるようにしました。
Env変数が使用可能な場合、Run ccommandは実行されますか?
run
コンテナを使用すると、-e
フラグで設定された環境変数が設定されます。
問題は、コンテナbuild
でDockerfileが読み取られるため、RUN
コマンドがnotそれらの環境変数を認識することです。 。
ビルド時に環境変数を設定する方法は、DockerfileにENV
行を追加することです。 ( https://docs.docker.com/engine/reference/builder/#/environment-replacement )
したがって、Dockerfileは次のようになります。
FROM node:latest
WORKDIR /src
ADD package.json .
ENV A YOLO
RUN echo "$A"
そして出力:
$ docker build .
Sending build context to Docker daemon 2.56 kB
Step 1 : FROM node:latest
---> f5eca816b45d
Step 2 : WORKDIR /src
---> Using cache
---> 4ede3b23756d
Step 3 : ADD package.json .
---> Using cache
---> a4671a30bfe4
Step 4 : ENV A YOLO
---> Running in 7c325474af3c
---> eeefe2c8bc47
Removing intermediate container 7c325474af3c
Step 5 : RUN echo "$A"
---> Running in 35e0d85d8ce2
YOLO
---> 78d5df7d2322
RUN
コマンドが起動されると、コンテナは環境変数が設定されていることを認識しています。