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

时间:2014-08-26 18:29:23

标签: mongodb continuous-integration integration-testing docker circleci

我试图为一组通过端点相互通信的Rails服务应用程序设置持续集成流程。我们的想法是配置CircleCI,以便在测试流程被触发时,它将为每个应用程序下拉预先配置的Docker镜像,为每个应用程序启动Docker容器,然后运行测试套件以测试全流程集成是否正常工作从一个应用程序到另一个其中一个服务应用程序使用MongoDB,因此它还需要与CircleCI自动安装的mongodb进行通信。流程应该是: 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存储库中。我在本地构建并提取了这些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的链接功能,但如果我理解正确,则需要在内部配置应用以寻找Docker设置的环境变量,例如DB_PORT_5000_TCP链接容器名为db,我希望尽可能避免修改内部配置。

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

修改 我已尝试将我的service_app配置为与正在运行的MongoDB容器进行通信(使用--link使用docker run -d -p 27017:27017 -p 28017:28017 --name mongodb dockerfile/mongodb mongod --rest --httpinterface,但这也无法正常工作。我提取了最新的mongo映像,然后运行:

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

按照该页面上的建议,然后运行

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

在我的service_app中,在构建之前,我已经配置了mongoid.yml:

MONGODB_PORT

我的理解是Docker在链接像这样的容器时应该设置env var,因此它应该连接到Mongo容器。我在容器中运行了MONGODB_PORT=tcp://172.17.0.95:27017,并设置了<!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>

但是,在我的本地计算机上,当我尝试连接到service_app进行查询时,它会返回

{{1}}

很明显,我没有正确的链接设置。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

问题与原点有关。如果从Docker容器内部访问localhost,则localhost指向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从外部访问客户端应用程序。