こんにちは、虎の穴ラボのはっとりです。
Docker Compose使ってますか?
開発環境をサクッと作ることが出来るDocker Composeですが、
今回は、個人的に便利だなーと思っている設定・機能をご紹介します。
皆さん、いくつご存知でしょうか。
目次
環境変数編
基本のやり方
アプリケーションの設定を環境変数で管理することも多いと思います。
Docker Composeで環境変数を扱うにはいくつかの方法があります。
- environment に値ごと直接書く
- environmentには環境変数名のみ書き、値は.envかホストPC側の環境変数に定義する
- env_file で指定したファイルに書く
1は最もシンプルでわかりやすいです。
# docker-compose.yml version: '3' services: rails-app: build: ./ environment: - DATABASE_URL=mysql2://user:pass@database:3306 database: # ....
2は機密情報や開発者間で異なる環境変数の値を設定する必要がある場合に使います。
※ そのため、.envはソース管理されないように除外設定しておいたほうがいいです。
# .env API_TOKEN=toranoana
# docker-compose.yml version: '3' services: rails-app: build: ./ environment: - API_TOKEN
docker-compose.yml内ではホストPCの環境変数による埋め込みが可能です。
ホストPC側に環境変数を定義しなくても、代わりに.envに定義してもdocker-composeコマンド実行時に環境変数として扱ってくれます。
environment
に値なしで追加した場合、ホストマシン側の環境変数か.envで定義した環境変数が使われます。
ホストマシン側の環境変数と.envに定義した環境変数だと、前者の方が優先されます。
下記のように、API_TOKEN=toranoana2を直接与えた場合は.envの値よりも優先されます。
API_TOKEN=toranoana2 docker-compose up
3の方法だと環境変数を別ファイル管理できます。2との違いこちらはコンテナ内の環境変数にしか使えません。
# app.env SECRET=toranoana-lab
# docker-compose.yml version: '3' services: rails-app: build: ./ env_file: - ./app.env
https://matsuand.github.io/docs.docker.jp.onthefly/compose/environment-variables/
応用
環境変数が多くなると全部をファイルに記述するのは大変です。
特に指定がない場合はデフォルト値を使えるようにしておくと楽です。
docker-compose.ymlはシェルの変数展開が使えるので
下記のようにデフォルト値を持ちつつ .env の値で上書きするということもできます。
※ こちらの方法では env_fileで指定したファイル は使えません。
# docker-compose.yml version: '3' services: rails-app: build: ./ environment: - API_URL=${API_URL:-http://example.com/api/v1/example}
変数展開を使えば環境変数に関わらず他の設定もデフォルト値を持ちつつ、.envファイルで上書きできます。
# .env PORT=3001
# docker-compose.yml version: '3' services: rails-app: build: ./ # PORT無指定時は 3000 ポートで起動し .envに指定があれば そのポートで起動する ports: - "${PORT:-3000}:3000"
ネットワーク編
docker-compose.yml に定義したコンテナ同士は service名をホスト名として使用できます。(v1では要links設定)
# docker-compose.yml version: '3' services: rails-app: build: ./ ports: - "${PORT:-3000}:3000" # my-database をホスト名として使用している environment: - DATABASE_URL=mysql2://user:pass@my-database:3306 - RAILS_ENV my-database: image: mysql:5.7 command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci ports: - "${MYSQL_PORT:-3306}:3306" environment: - MYSQL_ROOT_PASSWORD=rootpass - MYSQL_USER=user - MYSQL_PASSWORD=pass
異なるdocker-compose.ymlで起動しているコンテナ同士で接続
異なるdocker-compose.ymlで定義したコンテナ同士でも同じ様にservice名をホスト名として使用する方法があります。
同じ名前のnetworkに所属させることにより、サービス名をホスト名とした通信が可能になります。
この場合、どちらかのnetworkにはexternal: true
をつけて、作成済みのnetworkに所属させるようにします。
# docker-compose.yml version: '3' services: api-app: build: ./ networks: - default - my-shared-network ports: # ホストマシンへは8081でlistenさせている - '8081:8080' networks: my-shared-network: name: my-shared-network
# docker-compose.yml version: '3' services: rails-app: build: ./ environment: # コンテナ同士で接続しているので コンテナ内部のポートであることに注意 - API_URL=http://api-app:8080/api/v1/example networks: - default - my-shared-network networks: my-shared-network: name: my-shared-network external: true
external: true
がついていない方を先に起動する必要があります。
network設定無しで接続する方法 ※Docker DeskTop限定
コンテナ内からlocalhostを使うと自身のコンテナを指してしまいますが、
host.docker.internal
というホスト名を使うとホストマシンに向いてくれます。
これを使うと別のコンテナやホストマシンで起動しているアプリにも接続が可能になります。
※ただし、host.docker.internal
はDocker DeskTopでしか使えません。
networkの設定がいらないので設定もシンプルになりやすいです。
ただし、host.docker.internal
はホストマシンのホスト名なので、
接続するコンテナのlistenしているポートに合わせる必要はあります。
# docker-compose.yml version: '3' services: api-app: build: ./ ports: # ホストマシンへは8081でlistenさせている - '8081:8080'
# docker-compose.yml version: '3' services: rails-app: build: ./ environment: # ホストマシンへ接続しているので コンテナ内部からのポートでないことに注意 - API_URL=http://host.docker.internal:8081/api/v1/example
ボリューム編
Docker for Macを使っていて、どうしても読み込みが遅いなと感じることが多々ありましたが、下記の記事で紹介されているボリュームマウントのチューニングを試したところ劇的に速くなりました。
https://qiita.com/ysKey2/items/346c429ac8dfa0aed892 https://docs.docker.com/docker-for-mac/
:delegated
を付けるだけです。
コンテナ -> ホスト の変更に遅延が発生することを許容することでパフォーマンスが向上する仕組みのようです。
そのため、コンテナ内でコードを自動生成・修正する場合は注意が必要です。
# docker-compose.yml version: '3' services: api-app: build: ./ volumes: - ./:/var/www/app:delegated
その他
command に tail -f /dev/null
を指定してコンテナを起動しっぱなしにする。
Dockerコンテナはcommandに指定したプロセスが終了するとコンテナが停止します。
command に tail -f /dev/null
を指定すると停止せずに起動しっぱなしになってくれます。
※もちろんコンテナにtailがインストールされている必要はあります。
# docker-compose.yml version: '3' services: rails-app: build: ./ command: tail -f /dev/null
docker-compose up -d
でコンテナを起動しておいて
docker-compose exec (サービス名) sh
または docker-compose exec (サービス名) bash
(※alpineの場合はbashの代わりにash)でコンテナ内に入れます。
設定ファイルを分割して定義する
docker-composeコマンドでは compose ファイル を指定することができます。
複数のcompose ファイルがマージされた状態で扱われます。
同じキーの場合はより後のファイルの設定で上書きされます。
docker-compose -f docker-compose1.yml -f docker-compose2.yml -f docker-compose3.yml up -d
https://docs.docker.jp/compose/reference/overview.html
コマンドの-f
オプションを複数つけることで指定できますが、ホストマシンの環境変数や.envファイルでも指定することができます。
環境変数の場合は:
で区切ります。(※Windowsで使う場合は :
ではなく ;
のようです)
COMPOSE_FILE=docker-compose1.yml:docker-compose2.yml:docker-compose3.yml docker-compose up -d
または
# .envには下記のように定義されている # COMPOSE_FILE=docker-compose1.yml:docker-compose2.yml:docker-compose3.yml docker-compose up -d
まとめ
「知らないのがいくつかあった」、「全部知ってたよ」いろいろあると思います。
Docker Composeの全ドキュメントを読んだわけではないですし、新しいバージョンで新しい機能もどんどん追加されているのできっとこの他にも私が知らない便利機能があるかしれません。
これは便利だなと思うものがあったら教えて頂けると嬉しいです!
P.S.
■採用情報
yumenosora.co.jp
■ToraLab.fmスタートしました!
メンバーによるPodcastを配信中!
是非スキマ時間に聞いて頂けると嬉しいです。
■Twitterもフォローしてくださいね!
ツイッターでも随時情報発信をしています
twitter.com