devcontainerでdocker-composeを使う時にdocker-compose.ymlへの変数の受け渡し方
経緯
VSCodeのdevcontainer
用にdocker-compose.yml
を書いていて、 同じ文字列 を使うことが多々あるので変数化できないかを調べたので結果を残します。
結論
devcontainer
でdocker-compose
を使う場合はおとなしく、.env
を使うのことで目的は達成できます。
単体のDockerfile
ならdevcontainer
でもdevcontainer.json
の設定で.env
以外のファイルを読み込ませることは可能でした。
この当たりも最後の方に書きます。
調査詳細
.env
による環境変数の受けわたし
結論に書いた通りで、devcontainer
用のdocker-compose.yml
に環境変数を渡すのは.env
になります。
docker compose up
を直接実行する際には--env-file
で別のファイル名で指定することも可能です。
ですが、devcontainer
立ち上げ時のdocker compose up
コマンドはVSCodeが行うため、--env-file
を指定できません。
そのためコマンドに引数を渡さなくても自動で読み込まれる.env
で受け渡すことになります。
.env
とenv_file(environment)
は別物
僕自身混同していましたが.env
ファイルとdocker-compose.yml
内のenv_file
は別物です。
.env
主な用途はdocker-compose
がdocker-compose.yml
からコンテナをビルドするタイミングで読み込まれるdefault環境変数を書くファイルです。
docker-compose.yml
内に書かれた環境変数のキーに該当するキーが.env
にある場合、.env
の値が埋め込まれます。
たとえば
USER_NAME=vscode
CONTAINER_NAME=zenn_container
HOME_DIR=/home/${USER_NAME}
と書かれた.env
がある場合、以下のdocker-compose
が正常に動作します。
version: "3.4"
services:
zenn_cli_on_nodejs:
container_name: $CONTAINER_NAME
# ホスト名を明示的に指定する
hostname: localhost
build:
context: .
dockerfile: ./ubuntu/Dockerfile
args:
USER_ID: 1000
USER_NAME: $USER_NAME
GROUP_ID: 1000
GROUP_NAME: $USER_NAME
WORK_DIR: develop
environment:
- TZ=JST-9
ports:
- 8000:8000
volumes:
# ソースコードとdevcontainerを一緒に管理する場合は明示的にマウント先を指定
- ..:$HOME_DIR/develop:cached
- ~/.ssh:$HOME_DIR/.ssh
- .extensions:$HOME_DIR/.vscode-server/extensions
command: sleep infinity
$ docker-compose config
services:
zenn_cli_on_nodejs:
build:
args:
GROUP_ID: '1000'
GROUP_NAME: vscode
USER_ID: '1000'
USER_NAME: vscode
WORK_DIR: develop
context: /home/*****/develop/zenn-content/.devcontainer
dockerfile: ./ubuntu/Dockerfile
command: sleep infinity
container_name: zenn_container
environment:
TZ: JST-9
hostname: localhost
ports:
- published: 8000
target: 8000
volumes:
- /home/*****/develop/zenn-content:/home/vscode/develop:cached
- /home/*****/.ssh:/home/vscode/.ssh:rw
- /home/*****/develop/zenn-content/.devcontainer/.extensions:/home/vscode/.vscode-server/extensions:rw
version: '3.4'
補足ですが、docker compose up
のオプション--env-file
でファイル指定した場合も同じですタイミングで読み込まれます。
docker-compose.yml
内のenv_fileやenvironment
こちらはdocker-compose
がdocker-compose.yml
からコンテナをビルド完了後に、 コンテナに渡す 環境変数です。
そのため、env_file
やenvironment
も同様にdocker-compose.yml
内では使用できません。
正確にはただ空値状態なので、エラーにもならないけど求めてる状態にならないケースが出てきます。
devcontainer
を起動する前にdocker-compose config
を実行すると値が入っていない状態なのが確認できます。
env_file
とenvironment
の違いはenvironment
はdocker-compose.yml
に直接環境変数を書く、env_file
は環境変数を外出したファイルを作成して読み込む形式になっただけです。
docker-compose config
を実行するとenvironment
に全部書いてenv_file
で環境変数が書かれたファイルを読み込んでもどちらも同じ結果が返ってきます。
--env-file
指定できる
(おまけ)DockerfileならDockerfile
単体で立ち上げる場合は、devcontainer.json
の設定で.env
以外の設定ファイルを指定することが出来ます。
``devcontainer.jsonに
runArgs`という設定があり、以下のように書くことが可能です。
{
...,
"runArgs": [
"--env-file", "<devcontainer.jsonから見た設定ファイルのパス>"
]
}
runArgs
と書いてある通り、docker run
コマンドに対する引数指定なのでdocker compose up
コマンドに対しては引数指定できません。
こちらのIssueでdocker-compose
用の upArgs
という設定ほしいよねってやりとりはあったみたいですが、そのまま流れてCloseされてますね・・・
まとめ
他にも
-
Extension fields
でどうにかできないか(文字列連結ができなくて断念) -
devcontainer.json
の設定でどうにかならないか(upArgs
ほしい・・・) -
postCreateCommand
とかにShellScript叩かせて(postCreateCommand
実行タイミングは既にコンテナ出来上がってる・・・)
とまぁ、色々試してみたのですが devcontainer
でdocker-compose
を使う場合は.env
の決め打ちでいいんじゃないかなって気がしてます。
もしコンテナに対してenv
ファイル使いたい場合はそちらの名前をdevcontainer.env
などの名前に変えるほうが自然かもしれません。
とりあえずは今回はここまでにしました。
参考資料
Qiita - docker-compose.ymlの中で環境変数を展開する
Compose ファイル (docker-compose.yml) 内で環境変数を参照する
docker docs - Environment variables in Compose - The “.env” file
docker docs 日本語版 - Compose における環境変数 - .envファイル
docker docs - Environment variables in Compose - Using the “--env-file” option
docker docs 日本語版 - Compose における環境変数 - --env-fileオプションの利用
docker docs - Compose specification - environment
Discussion