1. ホーム
  2. docker

[解決済み] Dockerfileを散らかさずに、複数の環境変数を読み込むには?

2022-03-04 22:31:58

質問

大量の環境変数を持つ単純なDockerイメージに取り組んでいます。docker-composeのように環境変数ファイルをインポートすることは可能でしょうか?dockerファイルのドキュメントを見ても、これに関する記述が見当たりません。

ドッカーファイル

FROM python:3.6

ENV ENV1 9.3
ENV ENV2 9.3.4
...

ADD . /

RUN pip install -r requirements.txt

CMD [ "python", "./manager.py" ]

質問を言い換えると、「Dockerfileで複数の環境変数を効率的に読み込むにはどうしたらいいか」ということになりますね。もし読み込むことができなければ、DockerfileをGitHubにコミットすることはできないでしょう。

どのように解決するのか?

はい、いくつかの方法があります。

Dockerコンポーズ

Docker Composeでは、ファイル自体に環境変数を与えることも、外部のenvファイルを指すこともできます。

# docker-compose.yml
version: '2'
services:

  service-name:
    image: service-app
    environment:
    - GREETING=hello
    env_file:
    - .env

ちなみに、少し関連した機能として、複数のComposeファイルを使用し、後続のファイルがそれぞれ他のファイルに追加できるのも良い点です。つまり、上記のようにベースを定義しておけば、(例えばランタイム環境ごとに)こんなことができるようになります。

# docker-compose-dev.yml
version: '2'
services:

  service-name:
    environment:
    - GREETING=goodbye

そして、このように実行することができます。

docker-compose -f docker-compose.yml -f docker-compose-dev.yml up

Dockerのみ

Dockerのみで行う場合は、エントリーポイントやコマンドで中間スクリプトを実行するように、このようにします。

#Dockerfile

....

ENTRYPOINT ["sh", "bin/start.sh"]

そして、スタートスクリプトに

#!/bin/sh

source .env

python /manager.py

私は この関連回答はこちら 過去に自分自身の参考にしたことがある。

PID 1の更新について

コメントでの発言を補足すると、エントリーポイントをシェルやPythonスクリプトにした場合、おそらく Unixシグナル (stop,killなど)がプロセスに渡されることはありません。これは、そのスクリプトが プロセスID 1 Linux/Unixでは、このPIDが子プロセスにシグナルを転送することが期待されていますが、あなたが明示的に実装しない限り、それは起こりません。

これを修正するために、initシステムをインストールすることができます。私が使っているのは Yelpのdumb-init . このレポには、もう少し理解したいという方のために詳細な説明もありますし、ただ "インストールして忘れたい" という方のために簡単なインストール手順もあります。