Docker Compose 環境変数とは?設定方法と活用例を徹底解説
主に以下の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_KEY
と DATABASE_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.yml
のenvironment
セクションで、値として${変数名}
の形式でホストの環境変数を指定します。 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.yml
のenvironment
セクションでの定義ミス(スペルミス、構文エラーなど)。.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.yml
のenvironment
セクションで、値を引用符で囲まずに${ホストの環境変数名}
のように記述した場合、ホストの同名の環境変数が展開されてしまいます。意図しない値がコンテナに渡る可能性があります。
特殊文字や空白を含む環境変数の扱い
- トラブルシューティング
.env
ファイルやdocker-compose.yml
で値を定義する際に、必要に応じてシングルクォート (') またはダブルクォート (") で値を囲んでください。特に空白を含む場合はクォートすることを推奨します。
- 原因
- 環境変数の値に空白や特殊文字が含まれている場合、適切にクォートしないと意図しない挙動を引き起こすことがあります。
複数の .env ファイルの扱い
-
トラブルシューティング
- 複数の環境設定ファイルを管理したい場合は、
docker-compose.yml
のenv_file
オプションを使用して明示的に指定できます。
version: '3.8' services: web: image: nginx:latest ports: - "80:80" env_file: - .env - .env.production
この例では、
.env
と.env.production
の両方のファイルが読み込まれます。同じ変数が両方のファイルで定義されている場合は、後に読み込まれたファイルの値で上書きされます。 - 複数の環境設定ファイルを管理したい場合は、
-
- Compose はデフォルトで同じディレクトリにある
.env
ファイルを一つだけ読み込みます。複数の.env
ファイルを読み込ませる設定はデフォルトではありません。
- Compose はデフォルトで同じディレクトリにある
Compose ファイルのバージョンによる挙動の違い
- トラブルシューティング
- 可能であれば、最新の Docker Compose のバージョンを使用することを推奨します。Compose ファイルの
version
を確認し、必要に応じて更新してください。
- 可能であれば、最新の Docker Compose のバージョンを使用することを推奨します。Compose ファイルの
- 原因
- 古い 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.yml
の environment
セクションで PORT
と MESSAGE
という2つの環境変数を定義しています。Node.jsアプリケーション (app.js
) 内では、process.env.PORT
と process.env.MESSAGE
を使用してこれらの環境変数の値を取得しています。もし環境変数が定義されていなければ、デフォルト値(3000
と 'Hello from Docker!'
)が使用されます。
実行方法
- 上記の
app.js
とdocker-compose.yml
を同じディレクトリに保存します。 - ターミナルでそのディレクトリに移動し、
docker-compose up -d
を実行します。 - ブラウザで
http://localhost:8080
にアクセスすると、「Welcome to my awesome app!」というメッセージが表示されます。 - 環境変数を変更して再起動するには、
docker-compose.yml
のenvironment
の値を変更するか、.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.yml
の environment
セクションで ${変数名}
の形式で参照しています。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.yml
のcommand
セクションで、コンテナ起動時にアプリケーションにコマンドライン引数として設定情報を渡します。
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 によってライフサイクルが管理される。
- 欠点
- 導入と設定が複雑になる。
- 外部サービスへの依存性が生まれる。
- アプリケーション側で外部サービスと連携する処理を実装する必要があります。
- 利点
- 大規模で複雑なアプリケーションの設定管理に適している。
- 動的な設定変更を容易に行える場合がある。
- セントラルな管理により一貫性を保ちやすい。
- 方法
より大規模な環境では、外部の構成管理サービスを利用してアプリケーションの設定を一元的に管理し、実行中のコンテナからこれらのサービスにアクセスして設定を取得する方法があります。