質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.60%

二つのdocker-compose.yml同士でAPI通信を行いたい。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 855

score 12

前提・実現したいこと

docker-compose.ymlで立ち上げたアプリが二つあります。この二つのアプリ間でAPI通信を行いたいです。

困っている事

それぞれのアプリをdocker-compose upで立ち上げlocalhost:3000localhost:4000でブラウザに表示出来るようになっています。そして片方のアプリで新規ユーザーを作成するとAPIを通してそのデータがもう一つのアプリで反映されるようになっています。

問題はユーザー作成時にjson parseエラーが出ることです。原因はdocker-composeで立ち上げたアプリ同士はネットワークが独立しており通信出来ないまではわかっているのですが、composeファイルの記述の仕方が分からない事です。

色々調べて試したのですが、どこがおかしいのか指摘して頂けないでしょうか?汗

お忙しい中申し訳ありません。。

エラー内容

JSON::ParserError in StoreManagers::RegistrationsController#create

詳しい情報

以下はディレクトリの構造です

root
┣ app1
┃  ┝ docker-compose.yml
┃  ┗ Dockerfile
┃
┣ app2
┃  ┝ docker-compose.yml
┃  ┗ Dockerfile
┃
┃

app1app2はどちらもコンテナの構成は同じで、一つのアプリにappdbwebとそれぞれの3つのコンテナから構成されています。

該当のソースコード

docker-compose.yml

version: '3'
services:
  app:
    build:
      context: .
    env_file:
      - ./environments/db.env
    command: bundle exec puma -C config/puma.rb
    volumes:
      - .:/new_reserve_app
      - public-data:/new_reserve_app/public
      - tmp-data:/new_reserve_app/tmp
      - log-data:/new_reserve_app/log
    depends_on:
      - db
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    volumes:
      - db-data:/var/lib/mysql
  web:
    build:
      context: containers/nginx
    volumes:
      - public-data:/new_reserve_app/public
      - tmp-data:/new_reserve_app/tmp
    ports:
      - 3000:80
    depends_on:
      - app
    tty: true
    stdin_open: true
    networks:
      - smart_yoyaku_portal_site_default
networks:
  smart_yoyaku_portal_site_default:
    external: true
docker-compose.yml

version: '3'
services:
  app:
    build:
      context: .
    env_file:
      - ./environments/db.env
    command: bundle exec puma -C config/puma.rb
    volumes:
      - .:/webapp
      - public-data:/webapp/public
      - tmp-data:/webapp/tmp
      - log-data:/webapp/log
    depends_on:
      - db
  db:
    image: mysql:5.7
    env_file:
      - ./environments/db.env
    volumes:
      - db-data:/var/lib/mysql
  web:
    build:
      context: containers/nginx
    volumes:
      - public-data:/webapp/public
      - tmp-data:/webapp/tmp
    ports:
      - 4000:80
    depends_on:
      - app
    tty: true
    stdin_open: true
    networks:
      - new_reserve_app_default
networks:
  new_reserve_app_default:
    external: true

Dockerfileは共通です

Dockerfile

FROM ruby:2.6.5

# リポジトリを更新し依存モジュールをインストール
RUN apt-get update -qq && \
    apt-get install -y build-essential \
                       nodejs

# yarnパッケージ管理ツールインストール
RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
    echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
    apt-get update && apt-get install -y yarn

# Node.jsをインストール
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - && \
    apt-get install -y nodejs

# ルート直下にwebappという名前で作業ディレクトリを作成(コンテナ内のアプリケーションディレクトリ)
RUN mkdir /webapp
WORKDIR /webapp

# ホストのGemfileとGemfile.lockをコンテナにコピー
ADD Gemfile /webapp/Gemfile
ADD Gemfile.lock /webapp/Gemfile.lock

# bundle installの実行
RUN gem install bundler:2.1.4
RUN bundle install

# ホストのアプリケーションディレクトリ内をすべてコンテナにコピー
ADD . /webapp

# puma.sockを配置するディレクトリを作成
RUN mkdir -p tmp/sockets

試したこと

その1

docker-compose upした時に自動で作成されるnetwork情報を確認しdocker network lsコマンドで確認し、docker-compose.ymlwebの欄にnetwork:として書き込んだ。
そもそもwebの欄に書き込むので合っているのか分からない。

NETWORK ID          NAME                               DRIVER              SCOPE
432ad7870bfb        bridge                             bridge              local
47b4c16713f8        host                               host                local
a8f34f823a4e        new_reserve_app_default            bridge              local
c027fb39190d        none                               null                local
d834ad97970d        smart_yoyaku_portal_site_default   bridge              local
その2

共通のnetworkをdocker network createで作成。そのnetworkをそれぞれのdocker-compose.ymlに書き込み、pingコマンドで通信できているか確かめた。
pingで通信は出来ていたがjson parseエラーが返ってきた。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

それぞれの docker-compose.yml を確認すると、
別の既存の network に web サービスを接続する設定となっています:

  web:
# ---略---
    networks:
      - smart_yoyaku_portal_site_default
networks:
  smart_yoyaku_portal_site_default:
    external: true
  web:
# ---略---
    networks:
      - new_reserve_app_default
networks:
  new_reserve_app_default:
    external: true

参考: Use a pre-existing network | Networking in Compose | Docker Documentation

また、それぞれの app と db は networks の設定がないため、
それぞれの docker-compose up 時に作成された default ネットワークに
サービスが接続した状態となります

アプリケーション サービス network
app1 app app1_default
app1 db app1_default
app1 web smart_yoyaku_portal_site_default
app2 app app2_default
app2 db app2_default
app2 web new_reserve_app_default

サービス同士の直接の接続は同じ network に属するサービス同士でしか接続ができません

参考: Specify custom networks | Networking in Compose | Docker Documentation

解決策

例えば、それぞれのディレクトリーに
結合テスト用の docker-compose.integration.yml を作成します
以下の例は、app1 を先に起動する場合です

app1 側:

version: '3'
services:
  web:
    networks:
      default:
      public:
        aliases:
          - api
networks:
  public:

app2 側:

version: '3'
services:
  web:
    networks:
      default:
      app1_public:
        aliases:
          - front
networks:
  app1_public:
    external: true

そして、結合テストのためにサービスを起動するときは
どちらのアプリケーションでも次のコマンドを実行します:

docker-compose -f docker-compose.yml -f docker-compose.integration.yml up

このようにすると、
それぞれのアプリケーションの web サービスだけは、
alias で定義した別名を使い、お互いの web サービスにアクセスができます:

アプリケーション サービス network
app1 app app1_default
app1 db app1_default
app1 web app1_default, app1_public
app2 app app2_default
app2 db app2_default
app2 web app2_default, app1_public

参考: Compose file version 3 reference | Docker Documentation

JSON::ParserError について

ping 等でネットワーク要因との切り分けを行った後、
次の方法のいずれかで詳細を確認すると良いかもしれません

  • stacktrace を確認
  • アプリケーションの API アクセス処理の前後にログを追加
  • API アクセスのためのライブラリーのログ出力レベルの変更
  • デバッグツールによる API レスポンスの確認

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/06 22:48

    すみません。初歩的なミスをしていました汗

    コマンドを訂正して打ち直したら無事に起動できました!
    その後2つのアプリを起動→コンテナに入る→pingコマンドでアクセスできるか確認しようとしたのですが、繋がっていないようでした。
    よく確認するとdocker-compose.integration.ymlファイルのnetworkの指定先がそれぞれpublicとapp_publicで違うようなのですが、同じネットワーク名を書かなくておkなのでしょうか?

    過去にdocker network createコマンドでネットワークを作成し、そのネットワーク名を各docker-composeファイルに書き込んだらpingで通信が通ったのですが、それではダメなのでしょうか?

    質問沢山してしまい申し訳ありません汗

    キャンセル

  • 2020/09/06 23:03

    ping の際、"web" ではなく
    alias で指定している "api" または "front" で確認してみるといかがでしょうか?
    こちらの検証では到達が確認できました

    root@580291ddfd55:/# ping api
    PING api (192.168.192.2): 56 data bytes
    64 bytes from 192.168.192.2: icmp_seq=0 ttl=64 time=0.155 ms

    ネットワークは Docker Compose で作成されると、
    ネットワーク名にはディレクトリー名がプレフィックスとして追加されます
    もし app1 のディレクトリー名が実際は異なっている場合は
    app2 の方のネットワーク名のプレフィックスを実際のディレクトリー名に合わせてください

    先に docker コマンドでネットワークを作る方法でも
    うまくやればおそらく実現可能と思われます
    なるべく Docker Compose を使った方が管理が煩雑にならないだろうということで
    できる限り Docker Compose を利用して回答しました

    キャンセル

  • 2020/09/10 15:27

    お忙しい中回答ありがとうございました!

    あれからdocker-composeでnetworkを設定する方法を試したのですが、うまくいかずコマンドでとりあえずnetworkを作成しpingコマンドで確認しました。

    お忙しい中回答してくださりありがとうございました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.60%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る