Dockerの.env、置いただけじゃ動かない!?環境変数の読み込ませ方備忘録

完全にやらかしました。

Dockerを使っているとき、「.envファイルに環境変数情報書いたし、同じ階層に置いたからこれでコンテナ内でも読み込めるっしょ!」と余裕をぶっこいていたら、全然読み込まれていませんでした。

というわけで、初歩的すぎて逆にハマる「Docker Composeでの環境変数の扱い」について、自分用の備忘録として残しておきます。

そもそも何が起きていたのか

「.envファイルは、docker-compose.yml内での変数展開には使われるけど、勝手にコンテナの中には渡されない」

これです。これに尽きます。

例えば、.envにこう書いてあるとします。

# .env
MY_SECRET_KEY=super_secret_password

Docker Composeはこれを読み取ってくれます。でもそれは、あくまでdocker-compose.ymlの中で ${MY_SECRET_KEY} と書いたときに展開してくれるだけで、明示的に指定しない限り、コンテナの中(アプリケーション側)には渡らないんですね。

解決策は2パターンあります。

1. 環境変数定義ファイルを読み込ませる方法 (env_file)

一番手っ取り早いのがこれです。「環境変数を定義したファイルを丸ごとコンテナに読み込ませたいんじゃ!」という時は env_file を使います。

version: '3.8'

services:
  app:
    image: my-app-image
    # ここでファイルを指定する
    env_file:
      - .env
      # もちろん、.env 以外のファイルも指定できます
      # - .env.production 

こうすると、指定したファイルに書いてある変数がそのままコンテナ内の環境変数としてセットされます。

ちなみに、.env は指定しなくてもDocker Composeが勝手に読み込んでくれますが、それはあくまでyml内での変数展開用です。コンテナ内で環境変数として使いたい場合は、こうして明示的に指定する必要があります。 逆に言えば、この env_file を使えば、.env に限らず mysql.envapp.env のように、役割ごとに分割した別のファイルを読み込ませることもできるので便利です。

2. 環境変数を個別に指定する (environment)

ファイル丸ごと読み込ませない場合、コンテナ側で環境変数を使いたいなら、ここで「どの変数を渡すか」を必ず指定しなくてはいけません。

パターンA:.envの値をそのまま渡す

キー名だけ書くと、Docker Composeがホスト側(つまり読み込んだ.envの値)から同じ名前の変数を探して割り当ててくれます。

⚠️ 【最重要】ここを省略すると変数がコンテナに渡らないので注意!

.env ファイルがあっても、ここで指定しない限りコンテナには届きません。一番のハマりポイントです。

version: '3.8'

services:
  app:
    image: my-app-image
    environment:
      - MY_SECRET_KEY  # キー名だけ書くと、ホスト(.env)の値をそのままパススルーする

パターンB:明示的に値を指定する(あるいは名前を変える)

ここが一番の勘違いポイントでした。.env の値を使いたいなら、変数展開 ${} を使う必要があります。

version: '3.8'

services:
  app:
    image: my-app-image
    environment:
      # コンテナ内の APP_KEY という変数に、.envの MY_SECRET_KEY の値を入れる
      - APP_KEY=${MY_SECRET_KEY}

これなら、コンテナ側で期待している変数名と、.env 側の管理名が違っていても対応できます。何が渡されているかがymlを見るだけでわかるので、可読性はこっちの方が高いかもしれません。

まとめ

  • env_file: 定義ファイルを丸ごと渡す。別のファイルも指定できて便利。
  • environment: 個別に渡す。中身が見えやすい。

「.env置いたのに動かない!」となったら、だいたいこの記述忘れが原因です。 これでもう同じミスはしないはず……多分。