こんにちは。エンジニアの中西です。
今回は docker-compose の yml ファイルにて、環境変数が展開されずにハマった事について書きたいと思います。
docker-compose は Impulse でも使っています。複数のコンテナから構成される Impulse を yml ファイルで管理できて便利です。
yml ファイルに環境変数を定義しておき、実行環境毎に変数値を設定する事も可能なのですが、環境によっては設定した値が展開されず。。という事象に遭遇しました。
実行環境
- OS : Ubuntu 16.04
- docker : v17.09.0-ce
- docker-compose : v1.17.0
- docker-compose.yml : v3.3
準備
それでは、イメージのバージョンを環境変数で設定できるようにymlファイルを記述してみます。
version: '3.3' services: envtest: image: envtest-node:${IMAGE_VERSION:-invalid} : (省略)
イメージのバージョンを環境変数 IMAGE_VERSION
で変更可能としています。
環境変数の指定がない場合は invalid
が設定されます。
続いて、イメージが存在している事を確認します。
$ docker images envtest-node
REPOSITORY TAG IMAGE ID CREATED SIZE
envtest-node latest fedc1d9b97ce 1 weeks ago 933MB
バージョンは latest
です。
実行してみる
まずは環境変数を指定せずに実行してみます。
$ docker-compose up -d envtest Pulling envtest (envtest-node:invalid)... ERROR: pull access denied for envtest-node, repository does not exist or may require 'docker login'
環境変数が設定されていないので、デフォルトのinvalid
が設定されました。
当然ですが、envtest-node:invalid
というイメージは存在していないので docker pull
で取得しようとしていますが、ログインしていないためエラーとなっています。
では、環境変数を指定して実行します。
# バージョン`latest`を設定 $ export IMAGE_VERSION=latest # 実行 $ docker-compose up -d envtest Pulling envtest (envtest-node:invalid)... ERROR: pull access denied for envtest-node, repository does not exist or may require 'docker login'
エラー。
バージョン部分がデフォルト値の invalid
となっていますね。。
設定した環境変数が反映されていないようですので、確認してみます。
$ echo ${IMAGE_VERSION} latest
ちゃんと設定されていますね。
では、docker-compose.yml の environment に設定値含めて追加してみます。
version: '3.3' services: envtest: image: envtest-node:${IMAGE_VERSION:-invalid} environment: - IMAGE_VERSION=latest : (省略)
再度実行します。
$ docker-compose up -d envtest Pulling envtest (envtest-node:invalid)... ERROR: pull access denied for envtest-node, repository does not exist or may require 'docker login'
エラー。同じですね。
どうすれば展開されるのか
docker-composeは .env
という環境ファイルにデフォルトの環境変数を定義できるようなので、設定してみます。
$ vi .env
IMAGE_VERSION=latest
上記の1行を設定して保存し、実行してみます。
$ docker-compose up -d envtest Creating envtest ... Creating envtest ... done
おぉ、起動したようです! 確認してみます。
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 452f84eed286 envtest-node:latest "/bin/sh -c 'node sr…" 2 minutes ago Up 5 seconds 0.0.0.0:3333->3333/tcp envtest
バージョンlatest
で起動されています。
もしかして、.env
に環境変数が設定されていれば、実行時の環境変数設定値が反映されるのか?
公式サイトによると、
実行時に環境変数を指定すると、常に .env ファイル中で定義した変数を上書きします。同様にコマンドラインの引数で値を指定した場合も、指定した値を優先します。
とあります。
環境ファイル — Docker-docs-ja 17.06.Beta ドキュメント
試してみます。
$ export IMAGE_VERSION=none
存在しないバージョンを設定したので起動されないはずです。
$ docker-compose up -d envtest Creating envtest ... Creating envtest ... done
起動してしまいました。。
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f50c6736d2e7 envtest-node:latest "/bin/sh -c 'node sr…" 4 seconds ago Up 3 seconds 0.0.0.0:3333->3333/tcp envtest
バージョンは.env
に設定したlatest
ですね。
実行時の環境変数設定が反映されていない事がわかります。
原因は何?
とりあえず、 .envに書いておけば反映される 事は分かりましたが、冒頭で述べた通り環境によっては実行時の環境変数設定が反映されたりと、気持ちの悪い状態が続いていました。
そんな中、何気なくdockerのイメージ一覧を確認していたときでした。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker/compose 1.17.0 b5a188e247b9 3 weeks ago 19.6MB
docker-compose のイメージが存在しています。
そういえば以前から環境によっては存在していた気がしますが、あまり気にしてはいませんでした。
ちょっと公式サイトを確認してみましょう。
Docker Compose のインストール — Docker-docs-ja 17.06.Beta ドキュメント
docker-composeのインストール方法は3パターン存在するようです。
- curlコマンド実行によるインストール
- pipコマンド実行によるインストール
- dockerコンテナとしてインストール
※ビルドする方法もありますがここでは除外します
今回の環境は3番目ですね。
そういえば、実行時の環境変数設定が反映されている環境はどうなんだろう。
docker-composeのコンテナは存在しているのか確認してみる。
$ docker images docker/compose REPOSITORY TAG IMAGE ID CREATED SIZE
ありませんね。 curl、又はpipでインストールされている事になります。
まさか、インストールの方法で動きが変わる???
試しに、NGな環境のdocker-composeを削除し、curlで再インストールしてみましょう。
$ docker rmi <docker-composeのイメージID> : $ curl -L --fail https://github.com/docker/compose/releases/download/1.17.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose $ docker-compose version docker-compose version 1.17.0, build ac53b73 : $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE envtest-node latest fedc1d9b97ce 1 weeks ago 933MB
正しくインストールされ、docker-composeのイメージも存在していないですね。
実行する前に、環境変数の値を再確認しておきます。
# .envファイル IMAGE_VERSION=latest # 実行時の環境変数 $ echo ${IMAGE_VERSION} none
デフォルトはlatest
ですが、実行時にnone
としているので、none
となるのが理想です。
実行してみます。
$ docker-compose up -d envtest Pulling envtest (envtest-node:none)... ERROR: pull access denied for envtest-node, repository does not exist or may require 'docker login'
なんと!
イメージのバージョン指定がnone
となっています!
これは、.envの設定値を実行時の設定値で上書きされている事になります。
意図した動作をしてくれました。
終わりに
なぜコンテナとしてインストールすると環境変数の値が反映されないのかは調査できていませんが、
もし、同様の事象にハマった場合には、一度dockerのイメージ一覧を確認してみる事をおすすめします。
そこにdocker/compose
のイメージが存在していたら。。。
ブレインズテクノロジーでは「共に成長できる仲間」を募集中です
採用ページはこちら