设置多个Docker容器和MongoDB以在CircleCI中运行

我正在尝试为一组Rails服务应用程序设置一个连续的集成stream程,这些应用程序通过端点相互通信。 我们的想法是configurationCircleCI,以便在testingstream程被触发时,它将为每个应用程序下拉预configuration的Docker镜像,为每个应用程序启动Docker容器,然后运行一个testing套件来testing全stream程集成从一个应用程序通过其他。 其中一个服务应用程序使用MongoDB,所以它还需要与CircleCI自动安装的mongodb进行通信。 stream程应该是: client_app -> service_app -> mongodb但是,我有问题获取容器连接。

client_app的Dockerfile会安装Ruby和所有的依赖项,将这个repo添加到图像中,然后运行:

 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"] 

这两个Dockerfiles都存储在我们的私人Docker仓库中。 我已经在本地构build并拉出了这些Docker镜像,并确认它们正确启动。

在CircleCI上触发stream程时,我使用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应该configuration为在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 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的链接function,但是如果我理解正确,它需要应用程序在内部configuration以查找由Docker设置的环境variables,例如DB_PORT_5000_TCP如果链接的容器名为db ,并且我希望避免在可能的情况下修改内部configuration。

此外,我将需要service_app与运行的mongodb进行通信。 目前该应用程序被设置为连接到localhost:27017 ,这似乎是CircleCI启动Mongo服务,但我不确定Docker容器是否能够看到它。

编辑:我试图configuration我的service_app与正在运行的MongoDB容器交谈(使用受信任的Mongo版本使用 – --link但这也不工作,我拉了最新的mongo图像,然后跑:

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

如该页面上的build议,然后跑

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

在我的service_app中,在构build之前,我configuration了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> 

很显然,我没有这个链接设置的权利。 有任何想法吗?

问题与原点有关。 如果您从Docker容器内部访问本地主机,则本地主机指向泊坞窗本身,而不是主机服务器,因此呼叫未到达主机或其他泊坞窗。

如果你所有的docker都在同一台主机上,让它们通过本地主机相互通信的最简单方法是在运行时在容器之间共享一个networking。 首先正常运行后端,然后用–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

现在,任何共享networking的容器暴露和映射的所有端口都应该可以在任何docker的本地主机下访问。

  • 要从任何地方访问service-app-container,请使用machine:8080。
  • 要从主机服务器本地访问它,请使用localhost:8080。
  • 要从服务应用程序内部访问它,请使用locahost:8080。
  • 要从客户端应用程序访问服务应用程序,请使用localhost:8080

客户端应用程序只会暴露在3000以上的世界,如果你也暴露在有容器的docker。 暴露的端口不应该是这样混淆networking:

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

现在,您可以使用机器从外部访问客户端应用程序:3001。