Docker Compose 環境変数とは?設定方法と活用例を徹底解説

2025-05-31

主に以下の2つの方法で環境変数を設定できます。

docker-compose.yml ファイル内で直接定義する

サービス定義の中で environment セクションを使用します。キーと値のペアで環境変数を記述します。

version: '3.8'
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    environment:
      - API_KEY=your_secret_api_key
      - DATABASE_URL=postgres://user:password@host:port/database

この例では、web サービス(nginxコンテナ)に対して、API_KEYDATABASE_URL という2つの環境変数を設定しています。コンテナ内でこれらの環境変数を参照することで、アプリケーションはそれぞれの値にアクセスできます。

.env ファイルを使用する

プロジェクトのルートディレクトリなどに .env という名前のファイルを作成し、その中に環境変数を記述します。docker-compose.yml はこのファイルを自動的に読み込み、定義された環境変数をサービスに適用します。

.env ファイルの例:

API_KEY=another_secret_key
DATABASE_URL=mysql://another_user:another_password@another_host:another_port/another_database

docker-compose.yml ファイルでは、environment セクションで .env ファイルで定義した変数を参照できます。

version: '3.8'
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
    environment:
      - API_KEY=${API_KEY}
      - DATABASE_URL=${DATABASE_URL}

${変数名} の形式で .env ファイルの変数を参照できます。

  • 可読性
    docker-compose.yml ファイルや .env ファイルに設定がまとまっているため、設定内容が把握しやすくなります。
  • 柔軟性
    コンテナの起動時に環境変数を変更することで、同じイメージを異なる設定で実行できます。
  • 機密情報の管理
    APIキーやデータベースのパスワードなどの機密情報をコードに直接埋め込むことなく、安全に管理できます。.env ファイルをバージョン管理から除外することが推奨されます。
  • 設定の分離
    アプリケーションのコードと設定を分離できるため、コードを変更せずに環境に応じた設定を切り替えることができます(開発環境、テスト環境、本番環境など)。
  • Docker Secrets を利用すると、より安全に機密情報をコンテナに渡すことができます。
  • ホストマシンの環境変数をコンテナ内で利用することも可能です。docker-compose.ymlenvironment セクションで、値として ${変数名} の形式でホストの環境変数を指定します。
  • docker-compose.yml 内で直接定義した環境変数は、.env ファイルで同じ名前の変数が定義されている場合、.env ファイルの値で上書きされます。


環境変数がコンテナ内で認識されない

  • トラブルシューティング
    • docker-compose.yml ファイルの environment セクションの記述を再確認してください。キーと値のペアが正しく記述されているか、スペルミスがないかなどを確認します。
    • .env ファイルが docker-compose.yml と同じディレクトリにあるか確認してください。
    • .env ファイルの内容を確認し、KEY=VALUE の形式になっているか、不要な空白や特殊文字がないかなどを確認します。コメントは # で始める必要があります。
    • Compose を再起動 (docker-compose down してから docker-compose up) して、変更が反映されているか確認してください。
    • コンテナ内で環境変数が設定されているか確認します。コンテナに入り(docker exec -it <コンテナ名> sh など)、env コマンドを実行して環境変数の一覧を表示させます。意図した環境変数が表示されているか確認してください。
    • 参照する環境変数名 ${変数名}docker-compose.yml.env ファイルでの定義と一致しているか確認してください。
  • 原因
    • docker-compose.ymlenvironment セクションでの定義ミス(スペルミス、構文エラーなど)。
    • .env ファイルが正しい場所に配置されていない(通常は docker-compose.yml と同じディレクトリ)。
    • .env ファイルの形式が正しくない(KEY=VALUE の形式でない、コメントアウトされていない行があるなど)。
    • .env ファイルが docker-compose.yml より後に作成された、または変更後に Compose を再起動していない (docker-compose down してから docker-compose up を実行する必要がある場合があります)。
    • サービス定義内で ${変数名} の参照を間違えている。

.env ファイルが読み込まれない

  • トラブルシューティング
    • ファイル名が .env であることを確認してください。
    • docker-compose.yml.env ファイルが同じディレクトリにあることを確認してください。
  • 原因
    • .env ファイルの名前が . で始まっていない、または拡張子が .env でない。
    • docker-compose.yml.env ファイルと同じディレクトリにない。

ホストの環境変数が意図せずコンテナに渡ってしまう

  • トラブルシューティング
    • 静的な値を設定したい場合は、引用符で囲んでください(例: API_KEY="static_value")。ホストの環境変数を明示的に渡したい場合は ${HOST_VAR} のように記述します。
  • 原因
    • docker-compose.ymlenvironment セクションで、値を引用符で囲まずに ${ホストの環境変数名} のように記述した場合、ホストの同名の環境変数が展開されてしまいます。意図しない値がコンテナに渡る可能性があります。

特殊文字や空白を含む環境変数の扱い

  • トラブルシューティング
    • .env ファイルや docker-compose.yml で値を定義する際に、必要に応じてシングルクォート (') またはダブルクォート (") で値を囲んでください。特に空白を含む場合はクォートすることを推奨します。
  • 原因
    • 環境変数の値に空白や特殊文字が含まれている場合、適切にクォートしないと意図しない挙動を引き起こすことがあります。

複数の .env ファイルの扱い

  • トラブルシューティング

    • 複数の環境設定ファイルを管理したい場合は、docker-compose.ymlenv_file オプションを使用して明示的に指定できます。
    version: '3.8'
    services:
      web:
        image: nginx:latest
        ports:
          - "80:80"
        env_file:
          - .env
          - .env.production
    

    この例では、.env.env.production の両方のファイルが読み込まれます。同じ変数が両方のファイルで定義されている場合は、後に読み込まれたファイルの値で上書きされます。

    • Compose はデフォルトで同じディレクトリにある .env ファイルを一つだけ読み込みます。複数の .env ファイルを読み込ませる設定はデフォルトではありません。

Compose ファイルのバージョンによる挙動の違い

  • トラブルシューティング
    • 可能であれば、最新の Docker Compose のバージョンを使用することを推奨します。Compose ファイルの version を確認し、必要に応じて更新してください。
  • 原因
    • 古い Compose ファイルのバージョンを使用している場合、環境変数の扱いが最新バージョンと異なる場合があります。


例1: Webアプリケーションの設定

以下は、Node.jsで書かれたシンプルなWebアプリケーションの例です。このアプリケーションは、環境変数 PORT で指定されたポートでリッスンし、環境変数 MESSAGE で指定されたメッセージを表示します。

app.js (Node.js)

const http = require('http');

const port = process.env.PORT || 3000;
const message = process.env.MESSAGE || 'Hello from Docker!';

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end(`${message}\n`);
});

server.listen(port, () => {
  console.log(`Server listening on port ${port}`);
});

docker-compose.yml

version: '3.8'
services:
  web:
    image: node:18-alpine
    ports:
      - "8080:3000"
    environment:
      - PORT=3000
      - MESSAGE=Welcome to my awesome app!
    volumes:
      - ./app.js:/usr/src/app/app.js
    working_dir: /usr/src/app
    command: node app.js

この例では、docker-compose.ymlenvironment セクションで PORTMESSAGE という2つの環境変数を定義しています。Node.jsアプリケーション (app.js) 内では、process.env.PORTprocess.env.MESSAGE を使用してこれらの環境変数の値を取得しています。もし環境変数が定義されていなければ、デフォルト値(3000'Hello from Docker!')が使用されます。

実行方法

  1. 上記の app.jsdocker-compose.yml を同じディレクトリに保存します。
  2. ターミナルでそのディレクトリに移動し、docker-compose up -d を実行します。
  3. ブラウザで http://localhost:8080 にアクセスすると、「Welcome to my awesome app!」というメッセージが表示されます。
  4. 環境変数を変更して再起動するには、docker-compose.ymlenvironment の値を変更するか、.env ファイルを作成して値を定義し、docker-compose up -d を再度実行します。

例2: データベース接続情報

データベースに接続するアプリケーションでは、接続情報を環境変数として管理することが一般的です。

.env ファイル

DATABASE_HOST=mydb
DATABASE_USER=myuser
DATABASE_PASSWORD=mypassword
DATABASE_NAME=mydatabase

docker-compose.yml

version: '3.8'
services:
  web:
    image: my-web-app:latest
    ports:
      - "80:80"
    environment:
      - DATABASE_HOST=${DATABASE_HOST}
      - DATABASE_USER=${DATABASE_USER}
      - DATABASE_PASSWORD=${DATABASE_PASSWORD}
      - DATABASE_NAME=${DATABASE_NAME}
    depends_on:
      - db
  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=${DATABASE_USER}
      - POSTGRES_PASSWORD=${DATABASE_PASSWORD}
      - POSTGRES_DB=${DATABASE_NAME}
    volumes:
      - db_data:/var/lib/postgresql/data/
volumes:
  db_data:

この例では、.env ファイルにデータベースの接続情報を定義し、docker-compose.ymlenvironment セクションで ${変数名} の形式で参照しています。web サービスと db サービスの両方でこれらの環境変数を使用しています。

アプリケーションのコード内では、例えば Python であれば os.environ.get('DATABASE_HOST') のようにして環境変数の値を取得できます。

例3: APIキーなどの機密情報

APIキーやシークレットキーなどの機密情報は、コードに直接埋め込むべきではありません。環境変数や Docker Secrets を使用して安全に管理します。

.env ファイル

API_KEY=your_super_secret_api_key

docker-compose.yml

version: '3.8'
services:
  my_service:
    image: my-service:latest
    environment:
      - API_KEY=${API_KEY}

アプリケーション内では、環境変数 API_KEY を読み取って使用します。.env ファイルは通常、バージョン管理システムから除外します。

プログラミングにおける環境変数の参照

多くのプログラミング言語には、環境変数を読み取るための標準的な方法が用意されています。

  • Ruby
    ENV['VARIABLE_NAME']
  • Go
    os.Getenv("VARIABLE_NAME")
  • Java
    System.getenv("VARIABLE_NAME")
  • JavaScript (Node.js)
    process.env.VARIABLE_NAME
  • Python
    os.environ.get('VARIABLE_NAME') または os.environ['VARIABLE_NAME']


設定ファイルのマウント

  • docker-compose.yml の例
  • 方法
    ホストマシンの設定ファイル(例えば、JSON、YAML、INI形式など)をDockerコンテナ内の特定のパスにマウントします。アプリケーションは、そのパスから設定ファイルを読み込みます。
version: '3.8'
services:
  web:
    image: my-web-app:latest
    ports:
      - "80:80"
    volumes:
      - ./config.json:/app/config.json:ro # ホストの config.json をコンテナ内の /app/config.json に読み取り専用でマウント
    # ...
  • 欠点
    • 機密情報をファイルに保存する場合は、適切なアクセス権限管理が必要です。
    • 設定の変更をコンテナに反映させるために、コンテナの再起動が必要になる場合があります。
    • アプリケーション側で設定ファイルを読み込む処理を実装する必要があります。
  • 利点
    • 複雑な設定をファイルとして管理しやすい。
    • 環境変数よりも多くの情報を構造化して渡せる。
    • 設定ファイルの変更をコンテナに反映させるのが容易(再起動が必要な場合もあります)。

コマンドライン引数

  • docker-compose.yml の例
  • 方法
    docker-compose.ymlcommand セクションで、コンテナ起動時にアプリケーションにコマンドライン引数として設定情報を渡します。
version: '3.8'
services:
  web:
    image: my-web-app:latest
    ports:
      - "80:80"
    command: ["node", "app.js", "--port", "3000", "--message", "Hello from config!"]
    # ...
  • 欠点
    • 複雑な設定や機密情報の管理には不向き。
    • 設定の変更には docker-compose.yml の修正とコンテナの再作成が必要。
    • コマンドライン引数の解析処理をアプリケーション側で実装する必要があります。
  • 利点
    • シンプルな設定であれば、環境変数よりも直接的に値を渡せる。
    • アプリケーションの起動オプションとして自然な形式。

Docker Secrets

  • docker-compose.yml の例
  • 方法
    Docker Swarm モードで利用可能な機能ですが、スタンドアロンの Docker Compose でも x-secrets 定義と secrets セクションを使って機密情報を安全に管理できます。機密情報は Docker によって管理され、コンテナのファイルシステムや環境変数として安全にマウントできます。
version: '3.8'
x-secrets:
  api_key:
    file: ./secrets/api_key.txt
services:
  web:
    image: my-web-app:latest
    ports:
      - "80:80"
    secrets:
      - api_key
    # ...
secrets:
  api_key:
    external: false

アプリケーション内では、指定されたパス(通常は /run/secrets/<secret_name>)からシークレットファイルを読み取ります。

  • 欠点
    • 環境変数ほど直接的ではないため、ファイル読み込みの処理が必要。
    • 設定がやや複雑になる場合がある。
  • 利点
    • 機密情報を安全に管理できる。
    • Docker によってライフサイクルが管理される。

Docker Configs

  • docker-compose.yml の例
  • 方法
    Docker Secrets と同様に、Docker Swarm モードやスタンドアロンの Docker Compose で利用でき、機密情報だけでなく、設定ファイルなどの非機密な設定情報も安全に管理できます。
version: '3.8'
x-configs:
  app_config:
    file: ./config/app.config
services:
  web:
    image: my-web-app:latest
    ports:
      - "80:80"
    configs:
      - source: app_config
        target: /app/config
    # ...
configs:
  app_config:
    external: false

アプリケーション内では、指定されたパス (/app/config など) から設定ファイルを読み取ります。

  • 欠点
    • 環境変数ほど直接的ではないため、ファイル読み込みの処理が必要。
    • 設定がやや複雑になる場合がある。
  • 利点
    • 設定ファイルを安全かつ一元的に管理できる。
    • Docker によってライフサイクルが管理される。
  • 欠点
    • 導入と設定が複雑になる。
    • 外部サービスへの依存性が生まれる。
    • アプリケーション側で外部サービスと連携する処理を実装する必要があります。
  • 利点
    • 大規模で複雑なアプリケーションの設定管理に適している。
    • 動的な設定変更を容易に行える場合がある。
    • セントラルな管理により一貫性を保ちやすい。
  • 方法
    より大規模な環境では、外部の構成管理サービスを利用してアプリケーションの設定を一元的に管理し、実行中のコンテナからこれらのサービスにアクセスして設定を取得する方法があります。