连接dockerized应用程序网络以进行api调用

时间:2019-10-06 07:17:49

标签: docker docker-compose

我在连接点时有一些问题。

我设法将旧版应用程序和较新的应用程序进行了docker化,但是现在我需要通过API调用使它们彼此talk互通。

项目:

  • Project1 =使用project1_appnet(桥驱动程序)
  • Project2 =使用project2_appnet(桥驱动程序)
  • Project3 =使用project3_appnet(桥驱动程序)

在本地,我将这3个项目放在3个单独的文件夹中。每个项目都会有自己的appdbcache服务。

这是项目之一的docker-compose.yml。 (他们几乎所有相同的docker-compose.yml都具有不同的图像和卷​​路径)

version: '3'
services:
  app:
    build: ./docker/app
    image: 'cms/app:latest'
    networks:
      - appnet
    volumes:
      - './:/var/www/html:cached'
    ports:
      - '${APP_PORT}:80'
    working_dir: /var/www/html
  cache:
    image: 'redis:alpine'
    networks:
      - appnet
    volumes:
      - 'cachedata:/data'
  db:
    image: 'mysql:5.7'
    environment:
      MYSQL_ROOT_PASSWORD: '${DB_ROOT_PASSWORD}'
      MYSQL_DATABASE: '${DB_DATABASE}'
      MYSQL_USER: '${DB_USER}'
      MYSQL_PASSWORD: '${DB_PASSWORD}'
    ports:
      - '${DB_PORT}:3306'
    networks:
      - appnet
    volumes:
      - 'dbdata:/var/lib/mysql'
networks:
  appnet:
    driver: bridge
volumes:
  dbdata:
    driver: local
  cachedata:
    driver: local

问题:

  • 如何使他们能够通过API调用互相交谈? (在我的本地用于开发和生产环境)
  • 在生产中,设置将有所不同,它们将位于不同的计算机中,但仍位于同一VPC中,甚至是通过公用网络。设置是什么?

注意:

  • 我一直在查看link,但显然不推荐使用v3或不推荐使用
  • 通过执行以下操作,将curl从project1容器尝试到project2容器:
root@bc3afb31a5f1:/var/www/html# curl localhost:8050/login
curl: (7) Failed to connect to localhost port 8050: Connection refused

4 个答案:

答案 0 :(得分:2)

如果最终的设置是每个服务都将在物理上不同的系统上运行,那么实际上没有任何选择。一个系统无法直接访问另一系统上的Docker网络;服务1能够到达服务2的唯一方法是通过其主机的DNS名称(或IP地址)和发布的端口。由于这在不同的环境中会有所不同,因此建议您将该值设置为已配置的环境变量。

environment:
  SERVICE_2_URL: 'http://service-2-host.example.com/' # default port 80

一旦您解决了这一问题,大多数情况下就可以对单主机部署使用相同的设置。如果您的开发人员系统使用适用于Mac的Docker或适用于Windows的Docker,则应该可以使用special Docker hostname来访问其他服务

environment:
  SERVICE_2_URL: 'http://host.docker.internal:8082/'

(如果您在台式机上使用Linux,则必须知道主机的某些IP地址;不是localhost,因为它表示“此容器”,而不是docker0接口地址,因为那样会处于特定网络上,但类似于主机的eth0地址。)

您的另一个选择是“借用”另一个Docker Compose网络作为外部网络。如果您所有的Docker Compose设置都具有相同的名称,则会有些棘手。从一些实验看来,似乎Docker内部DNS总是会首先解析为您自己的Docker Compose文件,并且您必须了解诸如Compose分配的容器名称(这很难重构且稳定)之类的东西才能到达其他服务。

version: '3'
networks:
  app2:
    external:
      name: app2_appnet
services:
  app:
    networks:
      - appnet
      - app2_appnet
    environment:
      SERVICE_2_URL: 'http://app2_app_1/' # using the service-internal port
      MYSQL_HOST: db # in this docker-compose.yml

(我建议使用Docker Compose default network来声明自己的{{3}};这通常会使您删除文件中的所有networks:块而不会产生任何不良影响,但是在这种情况下,您需要声明networks: [default, app2_default]连接到两者。

当您开始考虑此问题时,也可以考虑使用多主机容器解决方案。 Kubernetes是重量级的,但是它将在集群中的任何节点上运行容器(您不必特别担心放置),并且它为您提供名称空间和自动DNS解析。您只需设置SERVICE_2_URL: 'http://app.app2/'即可指向另一个命名空间,而不必担心这些网络详细信息。

答案 1 :(得分:0)

如果您在本地运行此docker compose;给定的应用程序和数据库位于同一网络上-appnet- app 应该能够使用localhost:$ {DB_PORT}与 db 进行通话。

在生产中,如果app和db位于不同的机器上;应用可能需要使用IP或域名与数据库对话。

答案 2 :(得分:0)

考虑到要针对不同的docker部署使用不同的计算机,最好将它们放置在常规Web服务器(Apache2,Nginx)后面,然后使用简单的虚拟主机将流量从特定域路由到$APP_PORT。我更喜欢这样做,而不是直接将容器暴露给网络。这样,您还可以在同一台计算机上托管多个应用程序(如果愿意,可以 )。因此,我建议您不要尝试连接docker网络,而应使用“ 常规”网络。

答案 3 :(得分:0)

正在使用inspect和cURL。我想我找到了解决方案。

本地:

  • 在本地,我检查了容器并查看了NetworkSettings.Network.<network name>.Gateway的{​​{1}}
  • 然后我得到了公开的端口172.25.0.1
  • 然后,我在app1容器8050内进行了卷曲,以检查curl 172.25.0.1:8050/login是否可以对app2容器发出http请求。或app1
  • 反之亦然,我为docker exec -it project1_app_1 curl 172.25.0.1:8050/logincurl 172.25.0.1:80做了app2 -> app 1

唯一的问题是,当我们通过docker exec -it project2_app_1 curl 172.25.0.1:80重新启动时,Gateway值会发生变化

同样的生产方式:

我在网络和东西方面不是那个专业人士。我的产量估算为:

执行docker-compose up -d,这是因为Web服务器在自己的计算机上(即使使用负载平衡器)也指向应用程序。