Docker Composeは複数のDockerコンテナをまとめて立ち上げることができる便利なツールである。
いくつかのケースについて実例をあげながら設定方法を記載していこうと思う。

別docker-composeのコンテナを参照する

1つ目のdocker-composeでDBを、2つ目のdocker-composeでWebアプリを立ち上げて、WebアプリからDBを参照するケースを考える。
基本的には、networkで同一ネットワークに所属するように設定し、external_linksで外部コンテナにアクセスできるように設定すればよい。

DB用docker-compose.ymlの設定

version: '3'
services:
  postgres:
    image: postgres:latest
    container_name: "database"
  • このコンテナが所属するネットワーク名は、デフォルトで${ディレクトリ名}_defaultになる。今回のケースではdatabase_defaultになる。
    • database_defaultという名前が気持ち悪ければ、networks設定を行なってもいい。
  • 今回はdockerネットワーク外からアクセスしてないので、 ports設定は行なっていない。

Webアプリ用docker-compose.ymlの設定

version: '3'
services:
  web:
    build: .
    image: web-application
    container_name: "web-application"
    ports:
      - "8080:8080"
    environment:
      - DATABASE_URL=jdbc:postgresql://database:5432/research  # DBのURL
    external_links:
      - database  # 参照先コンテナ名を指定。エイリアスもつけられる
    networks:
      - database_default
networks:
  database_default:
    external: true
  • databaseコンテナと同じネットワークに所属させる必要がある。
    • databaseコンテナが所属するネットワーク名はdocker network lsでも確認できる。
  • external_linksを設定することで、別Docker Composeで立ち上げたdatabaseコンテナに到達可能になっている。
  • environmentの設定で、DBのURLを環境変数に設定しているが、ホスト名がexternal_linksで指定したコンテナ名databaseになっていることに注意。
  • Dockerfileの作成も必要だが今回は省略。

実行

DB側のフォルダで

docker-compose up

Webアプリ側のフォルダで

docker-compose up --build

同一Docker Compose内で別コンテナ(サービス)を立ち上げる

同一Docker Compose内でWebアプリとキャッシュサーバを立ち上げるケースを考える。
通常は特に何も考えず定義すればOK。

docker-compose.ymlの設定

version: '3'
services:
  web:
    build: .
    image: web-application
    ports:
      - "8080:8080"
  memcached:
    image: memcached:latest
  • 同一ネットワークに所属させる必要があるが、何も指定しなければデフォルトで同一ネットワークになるため特に設定は必要なし。
  • external_linksを使うために、webコンテナをdatabase_defaultに所属させたりしていると、memcachedコンテナも明示的に同じnetworkに所属させる必要があるので要注意。

実行

docker-compose up --build

外部APIを呼び出す

Docker Composeで立ち上げたWebアプリから、Dockerネットワーク外のAPIを呼び出すことを考える。
本当に外部APIを呼び出すパターンと、ホストマシン(localhost)で動かしているAPIを呼び出すパターンの2パターンを検証した。
外部APIはextra_hostsの設定が必要で、ホストマシン上のAPIにはhost.docker.internalでアクセスできる。

dockder-compose.ymlの設定

version: '3'
services:
  web:
    build: .
    image: web-application
    container_name: "web-application"
    ports:
      - "8080:8080"
    environment:
      - EXTERNAL_API_BASE=https://hoge.com/  # 外部APIのベースURL
      - INTERNAL_API_BASE=http://host.docker.internal:8081/fuga # ホストマシン上APIのベースURL
    extra_hosts:
      - "hoge.com:11.22.33.44"
  • extra_hostsに設定した内容が、コンテナ起動時に/etc/hostsに書き込まれる。
  • アプリケーション内では、EXTERNAL_API_URLINTERNAL_API_URLの二つの環境変数を読み込んで利用する。

docker-compose.yml内で動的に変数置き換えする

今回は、20190512の様な文字列を実行時に動的に取得して、コンテナ内でWORK_DIR環境変数として利用するケースを考える。
結論としては、docker-compose実行時の環境変数を設定するしかない。
公式ドキュメントはこちら

dockder-compose.ymlの設定

version: '3'
services:
  web:
    build: .
    image: web-application
    container_name: "web-application"
    ports:
      - "8080:8080"
    environment:
      - WORK_DIR=${TODAY}
  • docker-compose.yml内で変数置き換えできるのは以下の二つ。
    • env_file(デフォルトだと.env)で指定した環境変数
    • docker-compose実行時の環境変数
  • env_fileは静的な値しか設定できないので、今回は動的に値を設定できるdocker-compose実行時の環境変数を利用した。

実行

TODAY環境変数をシェルで設定してから、docker-compose upを実行する。

export TODAY=$(date "+%Y%m%d")
docker-compose up --build

その他Tips

  • Dockerイメージの名称はDocker Daemon上でユニークにする必要がある。なのでwebとかユニーク性が低い言葉は使わない方が良い。
  • docker-compose.ymlの変更が反映されてない気がするときは、とりあえずdocker-compose downを試してみる。
  • WEBアプリをローカル環境で開発するときの構成はこんな感じがいいと思う(いずれ記事を書く予定)
    • ミドルウェア(DBやmemcachedやnginxなど)はdocker-composeで立ち上げる
    • WEBアプリのリポジトリ内に、docker-composeで利用するファイルを一通り突っ込む
      • DBのマイグレーションSQL
      • nginxのconfファイル
    • docker-compose upで立ち上げ
    • ローカルPC上でアプリを起動
    • gradle bootRunとかactivator runとか
    • アプリからはdocker-composeで立ち上げたミドルウェアたちを参照する
    • これだとAutoReloadもできる

参考リンク