10
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DockerCompose Version2への移行でハマった点

Last updated at Posted at 2016-09-13

DockerComposeの設定ファイルのフォーマットをVersion1からVersion2に変更した際に、いくつかはまったところがあったので残しておきます。間違ってる点や、もっといい方法があれば教えてもらえると助かります。

システム構成

今回移行したシステムは、Railsアプリ2つとリバースプロキシ1つを持つ構成になっています。Railsアプリはどちらも同じイメージをベースとしており、設定だけが少し異なっています。実際はもうちょっとコンテナは多いですが、あまり関係ないので省略してます。

DockerContainerRelation.png

また、移行前後でDocker Engine, Docker Composeのバージョンアップも行っています。

移行前 移行後
Docker Engine 1.10 1.12
Docker Compose 1.6 1.8

移行前の設定

移行前の各アプリケーションのdocker-compose.ymlは以下のようになってます。imageは公式のものではなく独自に作っているものなので名前は適当に変えてます。

リバースプロキシとRailsアプリは通信できるようにしていますが、Docker Composeのexternal_linksは使ってません。これを使うと、リバースプロキシ配下のアプリを停止した時に、リバースプロキシまで停止してしまい、他のアプリへの接続ができなくなってしまったためです。1年くらい前に構築した時の情報なので、今は違うかもしれません。。。

  • リバースプロキシ(一部抜粋)
docker-compose.yml
nginx:
  image: hoge/nginx:latest
  ports:
    - "80:80"
  • Railsアプリ1(一部抜粋)
docker-compose.yml
redis:
  image: hoge/redis:latest
rails:
  image: hoge/rails:latest
  links:
    - redis:redis
  • Railsアプリ2(一部抜粋)
docker-compose.yml
redis:
  image: hoge/redis:latest
rails:
  image: hoge/rails:latest
  links:
    - redis:redis

移行後の設定(失敗1回目)

まずは、単純に書式を変更してみました。

  • リバースプロキシ(一部抜粋)
docker-compose.yml
version: '2'
services:
  nginx:
    image: hoge/nginx:latest
    ports:
      - "80:80"
  • Railsアプリ1(一部抜粋)
docker-compose.yml
version: '2'
services:
  redis:
    image: hoge/rails:latest
  rails:
    image: hoge/rails:latest
    depends_on:
      - redis
  • Railsアプリ2(一部抜粋)
docker-compose.yml
version: '2'
services:
  redis:
    image: hoge/redis:latest
  rails:
    image: hoge/rails:latest
    depends_on:
      - redis

単純に書式を変更しただけだと、リバースプロキシアプリからRailsアプリのコンテナに接続できなくなりました。Version1の時はこの設定で全てのコンテナが同じサブネットに属していたので接続できましたが、上記の設定だとそれぞれのアプリが別のネットワークに属するようになったことが原因です。そこで、全てのアプリが同じネットワークに属するように専用のネットワークを設定しました。

移行後の設定(失敗2回目)

  • リバースプロキシ(一部抜粋)
docker-compose.yml
version: '2'
services:
  nginx:
    image: hoge/nginx:latest
    ports:
      - "80:80"
    networks:
      - proxy_network
networks:
  proxy_network:
    external: true
  • Railsアプリ1(一部抜粋)
docker-compose.yml
version: '2'
services:
  redis:
    image: hoge/redis:latest
    networks:
      - proxy_network
  rails:
    image: hoge/rails:latest
    depends_on:
      - redis
    networks:
      - proxy_network
networks:
  proxy_network:
    external: true
  • Railsアプリ2(一部抜粋)
docker-compose.yml
version: '2'
services:
  redis:
    image: hoge/redis:latest
    networks:
      - proxy_network
  rails:
    image: hoge/rails:latest
    depends_on:
      - redis
    networks:
      - proxy_network
networks:
  proxy_network:
    external: true

アプリケーション共通のネットワークとしてproxy_networkを定義しました。ネットワークの作成は次のコマンドを実行しました。

command
$ docker network create --driver bridge proxy_network

共通のネットワークに属することで、リバースプロキシから各アプリケーションに接続できるようになりました。

新しい問題の発生

これで解決と思いましたが、今度はどちらか一方のRailsアプリがredisに接続ができなくなる現象が発生しました。Rails1アプリのredisコンテナのIPアドレスが172.21.0.2となっているのに、Rails1アプリのrailsコンテナからredisにpingを打つと172.21.0.5に向けて打っていました。この172.21.0.5は何かを調べるとRails2アプリのredisコンテナでした。Railsアプリではredisコンテナに接続するための接続先ホスト名を、DockerComposeで設定したサービス名redisとしていましたが、すべてのアプリケーションを共通ネットワークに属するようにしたことで、サービス名redisがRails1,Rails2の2つのアプリに含まれることになり、サービス名が重複したことで、コンテナ内蔵DNSが異なるIPアドレスを返すようになっていたことが原因のようです。この現象の調査では、Railsアプリを一つずつ動かすと正常に接続ができたため、原因を見つけるまでに結構時間がかかってしまいました。

そこで、この問題を解決するために2つの方法を考えました。

  • サービス名が重複しないように変更する
  • 外部アプリケーションからアクセス不要なコンテナは共通ネットワークではない別のネットワークに属するようにする

アプリケーションが増えるたびに新しいネットワークを追加するのは構成が複雑になるかな、と思いましたので今回は1つ目の方法で対応することにしました。今考えると、ネットワークを分けた方が素直で楽だったかもしれません。

移行後の設定(失敗3回目)

docker-compose.yml
version: '2'
services:
  nginx:
    image: hoge/nginx:latest
    ports:
      - "80:80"
    networks:
      - proxy_network
networks:
  proxy_network:
    external: true
  • Railsアプリ1(一部抜粋)
docker-compose.yml
version: '2'
services:
  rails1_redis:
    image: hoge/redis:latest
    networks:
      - proxy_network
  rails1:
    image: hoge/rails:latest
    depends_on:
      - rails1_redis
    networks:
      - proxy_network
networks:
  proxy_network:
    external: true
  • Railsアプリ2(一部抜粋)
docker-compose.yml
version: '2'
services:
  rails2_redis:
    image: hoge/redis:latest
    networks:
      - proxy_network
  rails2:
    image: hoge/rails:latest
    depends_on:
      - rails2_redis
    networks:
      - proxy_network
networks:
  proxy_network:
    external: true

これでrails1コンテナからrails1_redisコンテナ、rails2コンテナからrails2_redisコンテナのIPアドレスを正しく認識できるようになりました。

問題発生、再び

今度こそ解決だ、と思ったのですが今度はRailsアプリケーションでrails1_redisにアクセスしようとするとInvalidURIErrorが発生するようになりました。どうやらホスト名に_が含まれることが原因のようです。そこで、サービス名の_-に変更しました。DockerComposeとは直接関係ない問題ですが、サービス名の変更によるトラブルなので、一緒に書いておきます。

移行後の設定(最終形)

docker-compose.yml
version: '2'
services:
  nginx:
    image: hoge/nginx:latest
    ports:
      - "80:80"
    networks:
      - proxy_network
networks:
  proxy_network:
    external: true
  • Railsアプリ1(一部抜粋)
docker-compose.yml
version: '2'
services:
  rails1-redis:
    image: hoge/redis:latest
    networks:
      - proxy_network
  rails1:
    image: hoge/rails:latest
    depends_on:
      - rails1-redis
    networks:
      - proxy_network
networks:
  proxy_network:
    external: true
  • Railsアプリ2(一部抜粋)
docker-compose.yml
version: '2'
services:
  rails2-redis:
    image: hoge/redis:latest
    networks:
      - proxy_network
  rails2:
    image: hoge/rails:latest
    depends_on:
      - rails2-redis
    networks:
      - proxy_network
networks:
  proxy_network:
    external: true

これでやっと全てが正常に動くようになりました。

DockerCompose便利なんですけど、更新スピードが早くてついていくのが大変ですね。こまめにチェックしておかないといけないですね。

10
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?