SSD Nodes Learn メモリ 8GB — 年額 $66
ガイド Matt Connor著者 Matt Connor ・更新日 2026-08-01

Docker Composeの.env、env_file、environmentの違い

Docker Composeでenv fileと呼ばれる3つの仕組みを整理。.env、env_file、environmentの違いと優先順位、秘密情報をsecretsに置く理由をコマンドで確認します。

env fileと呼ばれる3つのもの

Docker Composeには、名前がよく似ている別々の仕組みが3つあります。.envファイルは、Composeがファイルを解析する前に、compose.yaml内の${VARIABLE}プレースホルダーを置換します。env_file:属性は、キーと値の組をコンテナの環境変数として読み込みます。environment:属性は、composeファイルに記述して、コンテナに変数を直接設定します。これらは互換性がありません。2つが同じキーを設定した場合、どちらが優先されるかは、文書化された優先順位で決まります。

このガイドでは、それぞれの仕組みの動作を示します。実行可能なコマンドで優先順位を確認します。その後、より重要な点を説明します。環境変数はdocker inspectを実行できる全員が読み取れるため、パスワードを環境変数に保存してはいけません。composeファイル全般に不慣れな場合は、まずVPS上のDocker Composeの基本を読んでから、このページに戻って設定を確認してください。

.envファイルはコンテナ用ではなくcomposeファイル用です

ディレクトリを作成し、その中に2つのファイルを配置します。

mkdir -p ~/envdemo && cd ~/envdemo
printf 'ALPINE_TAG=3.20\n' > .env
services:
  demo:
    image: alpine:${ALPINE_TAG}
    command: printenv ALPINE_TAG

次に、Composeが実際に解析した内容を確認します。

docker compose config

出力にはimage: alpine:3.20と表示されます。解析時に補間が行われるため、プレースホルダーはなくなっています。Composeは、composeファイルを格納しているプロジェクトディレクトリで.envを探し、見つかったすべての${NAME}を置換します。

次に、サービスを実行します。

docker compose run --rm demo

printenv ALPINE_TAGはステータス1で終了し、何も出力しません。コンテナ内にはこの変数が存在しないためです。これは最もよくある誤解です。.envが設定するのはcomposeファイルであり、プロセスではありません。POSTGRES_PASSWORD=hunter2を含む.envファイルを配置しても、composeファイルのどこかでそのファイルを参照しない限り、データベースには何の効果もありません。

${NAME:-default}は、変数が未設定または空の場合にフォールバック値を指定します。${NAME:?message}を指定すると、Composeは起動を拒否し、指定したメッセージを出力します。安全なデフォルト値がない場合は、この方法が適切です。

env_file でコンテナに変数を読み込む

env_file: 属性には、内容をコンテナの環境変数として読み込む1つ以上のファイルを指定します。

printf 'GREETING=from_env_file\nAPP_MODE=production\n' > app.env
services:
  demo:
    image: alpine:3.20
    command: printenv GREETING
    env_file:
      - ./app.env
docker compose run --rm demo

これは from_env_file を出力します。ファイル形式は、1行に1つの KEY=value 行を記述する単純な形式です。# でコメントを開始します。これは shell 形式ではありません。通常、引用符は値の一部として保持され、export の接頭辞は不要です。= 記号の前後に空白を入れないでください。入れると、KEY = value により、値の先頭に空白がある KEY という名前の変数が文字どおり作成されます。

env_file パスが存在しない場合はエラーとなり、Compose は停止します。ファイルが正当に存在しない場合があるなら、オプションとして指定します。

    env_file:
      - path: ./app.env
        required: false

environment で変数をインライン設定する

services:
  demo:
    image: alpine:3.20
    command: printenv GREETING
    environment:
      GREETING: from_environment

上記のマッピング形式と、- GREETING=from_environment を使用するリスト形式の2つの構文を使用できます。動作は同じです。リスト形式には追加の機能があります。値を指定しないキーだけを記述すると、docker compose を実行したシェルから変数を引き継ぎます。

    environment:
      - GREETING
GREETING=from_my_shell docker compose run --rm demo

これは from_my_shell を出力します。シェルで GREETING を設定せずに実行すると、Compose は何も設定せず、警告も表示しません。値の引き継ぎが通知なく失敗することには注意が必要です。空のパスワード変数で起動したサービスは、正常に起動したように見えますが、実際には無防備な状態になることがよくあります。

どれが優先されるか

Dockerでは優先順位が高い順に、コマンドラインの docker compose run -e、シェルまたは env file から値が補間される environment または env_file、compose file 内の通常の environmentenv_file、そしてイメージに組み込まれた ENV ディレクティブが優先されます。

日常の作業では、environment:env_file: より優先され、コマンドラインの -e はその両方より優先されます。1つのファイルで確認できます。

services:
  demo:
    image: alpine:3.20
    command: printenv GREETING
    env_file:
      - ./app.env
    environment:
      GREETING: from_environment
docker compose run --rm demo
docker compose run --rm -e GREETING=from_cli demo printenv GREETING

最初のコマンドは from_environment を出力します。つまり、environment:app.env の値を上書きしました。2番目のコマンドは from_cli を出力します。compose file 内の設定は、コマンドラインの設定を上書きしません。

コンテナが設定を適用していないように動作している場合は、推測しないでください。docker compose config は完全に解決されたファイルを出力し、docker compose config --environment は Compose が使用している補間変数を出力します。「env file が無視される」という報告の多くは、異なる2つのレベルで同じ値が設定されていることが原因です。

環境変数が漏えいする理由

environment: にパスワードを設定すると、コンテナの設定にディスク上で保存され、docker グループのすべてのユーザーから見える状態になります。

docker compose run -d --name leaky -e DB_PASSWORD=hunter2 demo sleep 300
docker inspect leaky --format '{{json .Config.Env}}'

出力には "DB_PASSWORD=hunter2" が平文で含まれます。同じ値を公開するパスがさらに3つあります。docker compose config はその値を端末に出力します。そのため、サポートフォーラムに貼り付けられることがあります。コンテナ内のすべてのプロセスは /proc/1/environ を読み取ることができ、すべての子プロセスがこの変数を継承します。また、アプリケーションのクラッシュハンドラーは、環境全体をログやエラーレポートにダンプすることがよくあります。

docker グループのメンバーシップは、実質的にホスト上の root 権限に相当します。したがって、これを権限境界として頼ることはできません。VPS上の最小権限ユーザーアカウントに関するガイドでは、共有サーバーでこのグループを制限する価値がある理由を説明しています。

Compose secretsで値をファイルに保持する

Composeはファイルベースのsecretsをサポートしています。値は環境変数に注入されるのではなく、ファイルとしてコンテナにマウントされます。

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password
secrets:
  db_password:
    file: ./db_password.txt

secretはコンテナ内の/run/secrets/db_passwordにマウントされます。スラッシュの後の名前は、トップレベルのsecrets:ブロックにあるsecret名です。

_FILEサフィックスは、postgresmysqlmariadbなどのDocker Official Imagesで使用される規約です。これらのentrypointスクリプトはVARNAME_FILEを確認し、ファイルを読み込んで、その内容を使用します。これはDockerの機能ではありません。そのため、イメージが実装している場合にだけ機能します。SOMETHING_FILEが使用されることを前提にする前に、イメージのドキュメントを確認してください。対応していないアプリケーションでも、通常は起動時にファイルを直接読み込めます。または、パスを渡して独自のentrypointに処理させることもできます。

実行中のコンテナ内から確認します。

docker compose exec db cat /run/secrets/db_password
docker compose exec db printenv POSTGRES_PASSWORD

最初のコマンドはパスワードを表示します。2つ目のコマンドは何も表示しません。値が環境変数に入っていないためです。これが目的です。このコンテナのdocker inspectには、無害なパスだけが表示されます。

secretは背後のファイルと同じレベルでしか保護されません。そのため、ホスト上のソースファイルを保護してください。

chmod 600 db_password.txt

VPSでの現実的な折衷案

多くのセルフホスト用イメージは _FILE 変数に対応していないため、環境変数が唯一の設定方法です。1人の管理者が運用するVPSでは、値をプロジェクトディレクトリ内の誰でも読み取れるファイルに置かず、gitからも除外することが現実的な目標です。

sudo install -o root -g root -m 600 /dev/null /etc/myapp/app.env
sudo nano /etc/myapp/app.env
    env_file:
      - /etc/myapp/app.env

install -m 600 は、モードを設定済みの状態でファイルを作成します。そのため、全員が読み取れる状態になる時間がありません。ファイルの所有者はrootなので、サーバー上のroot以外のユーザーは読み取れません。ただし、docker を実行できるユーザーは、コンテナから値を読み取れます。*.env.env.gitignore に追加し、代わりにキー名と空の値だけを記載した app.env.example をコミットしてください。コミットされたパスワードは、ローテーションが必要なパスワードです。

値をローテーションするには、サービスを再起動します。環境変数はコンテナプロセスの起動時に1回だけ読み込まれるため、ファイルを編集しただけでは反映されません。反映するには docker compose up -d --force-recreate db を実行します。これは VPS上でHTTPSを使用してn8nを動かす ガイドと同じ方法です。このガイドでは、暗号化キーをcomposeファイルの外部に保存します。

環境ごとの設定分割

Compose はデフォルトでプロジェクトディレクトリから .env を読み取ります。--env-file を使用すると、別の場所を指定できます。

docker compose --env-file .env.staging config

複数のファイルは順番に読み取られ、後のファイルが前のファイルを上書きします。秘密ではないデフォルト値はコミット済みのファイルに保存し、秘密情報はサーバー外に持ち出さないファイルに保存してください。env_file: でも同様に、重複するキーは最後に指定したファイルの値が有効になります。

FAQ

コンテナ内で .env ファイルが無視されるのはなぜですか?

無視されているわけではありません。.env ファイルは、compose ファイル内の ${NAME} プレースホルダーを置換するだけです。コンテナ内の変数を設定することはありません。値をコンテナに渡すには、environment: { KEY: "${NAME}" } を参照するか、代わりに env_file: ./that-file.env を使用します。

environment と env_file では、どちらが優先されますか?

environment: が優先されます。Docker のドキュメントに記載された優先順位では、environment 属性が env_file 属性より上位で、どちらもコマンドラインの docker compose run -e より下位です。両方の場所でキーを設定すると、env_file の値は通知なく使用されません。

Compose が使用する最終的な値を確認するにはどうすればよいですか?

docker compose config を実行すると、すべての補間を適用した完全に解決済みの compose ファイルが表示されます。すでに実行中のコンテナでは、docker inspect <container> --format '{{json .Config.Env}}' によってプロセスが受け取った値を正確に確認できます。

Compose の secrets は暗号化されますか?

いいえ。ファイルベースの secret は、/run/secrets/<name> に通常のファイルとしてコンテナへマウントされます。元のファイルも、ホストのディスク上に暗号化されない状態で保存されます。利点は暗号化ではなく、対象範囲を限定できることです。値はコンテナの環境変数、docker inspect の出力、環境変数を出力するクラッシュダンプに含まれません。

env ファイルで引用符やスペースを使用できますか?

KEY=value with spaces を使用し、引用符は付けないでください。Compose は行の残り全体を値として扱うため、引用符は通常、値の一部としてそのまま残ります。= の前後にはスペースを入れないでください。キーに末尾のスペースが含まれ、対応する値が見つからなくなります。