1

エンドポイントを介して相互に通信するいくつかの Rails サービス アプリのグループの継続的統合フローをセットアップしようとしています。アイデアは、テスト フローがトリガーされたときに、各アプリの事前構成された Docker イメージをプルダウンし、各アプリの Docker コンテナーを起動して、フルフロー統合が機能することをテストするテスト スイートを実行するように、CircleCI を構成することです。あるアプリから別のアプリへ。サービス アプリの 1 つは MongoDB を使用するため、CircleCI が自動的にインストールする mongodb とも通信する必要があります。フローは次のようになります。 client_app -> service_app -> mongodb ただし、コンテナーを接続するのに問題があります。

client_app の Dockerfile は、Ruby とすべての依存関係をインストールし、リポジトリをイメージに追加してから実行します。

RUN bundle install

EXPOSE 3000

CMD ["bundle", "exec", "rails", "s", "-e", "development", "-p", "3000"]

service_app の Dockerfile は同じことを行います。

RUN bundle install

EXPOSE 8080

CMD ["bundle", "exec", "rails", "s", "-e", "test", "-p", "8080"]

これらの Dockerfile は両方とも、プライベート Docker リポジトリに保存されています。これらの Docker イメージをローカルでビルドしてプルし、正しく起動することを確認しました。

CircleCI でフローがトリガーされると、circle.yml を使用して各画像をプルダウンします。これは私の circle.yml です (アプリ名は変更されています):

machine:
  services:
    - docker

dependencies:
  pre:
    - sed "s/<EMAIL>/$DOCKER_EMAIL/;s/<AUTH>/$DOCKER_AUTH/" < .dockercfg.template > ~/.dockercfg
    - docker pull myorg/service_app
    - docker pull myorg/client_app

test:
  override:
    - docker run -d -p 8080:8080 --name service_app myorg/service_app:docker-test
    - docker run -d -p 3000:3000 --env SERVICE_APP_URL=http://localhost:8080 --name client_app myorg/client_app:docker-test
    - docker ps -a
    - bundle exec rspec spec

client_app は SERVICE_APP_URL で service_app と通信するように構成する必要があります (内部的にアプリは への接続を開始しますENV['SERVICE_APP_URL'])。そのため、service_app コンテナーはポート 8080 で実行されているため、 に設定しましたhttp://localhost:8080が、機能しません。client_app のログを調べると、呼び出しを行う最初のビューで、次のように返されます。

Connection refused - connect(2) for "localhost" port 8080

docker ps -aコンテナーが正しく起動されているかどうかを確認するために、circle.ymlに追加しました。そのステップでの出力は次のとおりです。

CONTAINER ID        IMAGE                           COMMAND                CREATED             STATUS              PORTS                    NAMES
782d09c4f3db        myorg/client_app:docker-test    bundle exec rails s    3 seconds ago       Up 2 seconds        0.0.0.0:3000->3000/tcp   berserk_mcclintock   
64f8af8ab535        myorg/service_app:docker-test   bundle exec rails s    5 seconds ago       Up 4 seconds        0.0.0.0:8080->8080/tcp   furious_wozniak

したがって、コンテナが開始され、適切なポートが公開されているように見えますが、client_app はまだ service_app に接続していません。

私は Docker のリンク機能を使用することを検討しましたが、それを正しく理解してDB_PORT_5000_TCPいれば、リンクされたコンテナーの名前dbが .可能であれば内部構成を変更します。

さらに、実行中の mongodb と通信するには service_app が必要です。現在、アプリは に接続するように設定されてlocalhost:27017います。これは、CircleCI が Mongo サービスを開始するもののようですが、Docker コンテナーがそれを認識できるかどうかはわかりません。

編集: 実行中の MongoDB コンテナーと通信するように service_app を構成しようとしました (信頼できる Mongo ビルドを使用して使用し--linkますが、どちらも機能しません。最新の mongo イメージをプルしてから実行しました:

docker run -d -p 27017:27017 -p 28017:28017 --name mongodb dockerfile/mongodb mongod --rest --httpinterface

そのページで提案されているように、実行した

docker run -d -p 8080:8080 --name service_app --link mongodb:mongodb myorg/service_app:v1

私の service_app では、ビルドする前に、mongoid.yml を構成しました。

test:
  sessions:
    default:
      database: test
      hosts:
        -  ENV['MONGODB_PORT'] || 'localhost:27017' %>
      options:
        safe: true

私の理解では、Docker は、MONGODB_PORTこのようなコンテナーをリンクするときに var を設定する必要があるため、Mongo コンテナーに接続する必要があります。env私はコンテナの中を走り、それは固まっていたMONGODB_PORT=tcp://172.17.0.95:27017.

ただし、ローカル マシンで service_app に接続してクエリを作成しようとすると、

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
    <HEAD>
        <TITLE>Internal Server Error</TITLE>
    </HEAD>
    <BODY>
        <H1>Internal Server Error</H1>
    Could not connect to any secondary or primary nodes for replica set &lt;Moped::Cluster nodes=[&lt;Moped::Node resolved_address=nil&gt;]&gt;

        <HR>
            <ADDRESS>
     WEBrick/1.3.1 (Ruby/2.0.0/2014-02-24) at
     192.168.59.103:8080
     </ADDRESS>
        </BODY>
    </HTML>

明らかに、このリンク設定が正しくありません。何か案は?

4

1 に答える 1

1

問題は原点に関連しています。Docker コンテナー内から localhost にアクセスすると、localhost はホスト サーバーではなく Docker 自体を指すため、呼び出しはホストまたは他の Docker に到達しません。

すべての Docker が同じホスト マシン上にある場合、localhost を介してそれらを相互に通信させる最も簡単な方法は、実行時にコンテナー間でネットワークを共有することです。最初に通常どおりバックエンドを実行し、次に--netスイッチを使用して他のコンテナーを開始します。

docker run [other params] -d -p 8080:8080 --name service-app-container service_app_image docker run [other params] -p 3000:3000 --net="container:service-app-container" --name client-app-container client_app_image

これで、ネットワークを共有する任意のコンテナーによって公開およびマップされたすべてのポートが、任意の Docker から localhost の下で到達できるようになります。

  • どこからでも service-app-container にアクセスするには、machine:8080 を使用します。
  • ホスト サーバーからローカルにアクセスするには、localhost:8080 を使用します。
  • サービス アプリから内部的にアクセスするには、locahost:8080 を使用します。
  • クライアント アプリからサービス アプリにアクセスするには、localhost:8080 を使用します。

クライアント アプリは、コンテナーを持つ Docker で公開する場合にのみ、ポート 3000 経由で世界に公開されます。これはネットワークを混乱させるため、公開されたポートは同じであってはなりません。

docker run [other params] -d -p 8080:8080 3001:3000 --name service-app-container service_app_image docker run [other params] -p 3000:3000 --net="container:service-app-container" client_app_image

これで、machine:3001 を使用して外部からクライアント アプリにアクセスできるようになりました。

于 2014-12-18T01:27:38.023 に答える