两个 docker 容器无法通信

Posted

技术标签:

【中文标题】两个 docker 容器无法通信【英文标题】:Two docker containers cannot communicate 【发布时间】:2020-10-10 19:58:34 【问题描述】:

我有两个 docker 容器。一个容器是数据库,另一个是 Web 应用程序。 Web 应用程序通过此链接 http://localhost:7200 调用数据库。但是,Web 应用程序 docker 容器无法访问数据库容器。

我试过这个 docker-compose.yml,但不起作用:

version: '3'
services:
  web:
    # will build ./docker/web/Dockerfile
    build: 
       context: .
       dockerfile: ./docker/web/Dockerfile
    links:
      - graph-db
    depends_on:
     - graph-db
    ports:
     - "8080:8080"
    environment:
      - WAIT_HOSTS=graph-db:7200
    networks: 
      - backend

  graph-db:
    # will build ./docker/graph-db/Dockerfile
    build:
        ./docker/graph-db
    hostname: graph-db
    ports:
      - "7200:7200"

networks:
  backend:
    driver: "bridge"

所以我有两个容器: Web 应用程序:http://localhost:8080/reasoner 并且此容器调用位于不同容器中的 http://localhost:7200 中的数据库。 但是,Web 容器无法访问数据库容器。

解决方案

version: '3'
services:
  web:
    # will build ./docker/web/Dockerfile
    build: 
       context: .
       dockerfile: ./docker/web/Dockerfile
    depends_on:
     - graph-db
    ports:
     - "8080:8080"
    environment:
      - WAIT_HOSTS=graph-db:7200


  graph-db:
    # will build ./docker/graph-db/Dockerfile
    build:
        ./docker/graph-db
    ports:
      - "7200:7200"

并将 Web 应用代码中的 http://localhost:7200 替换为 http://graph-db:7200

【问题讨论】:

尝试在 graph-db 中将主机名更改为 localhost 【参考方案1】:

不要使用 localhost 在容器之间进行通信。网络是 docker 中的命名空间之一,因此容器内的 localhost 仅连接到该容器,而不连接到您的外部主机,也不连接到另一个容器。在这种情况下,请在您的应用中使用服务名称graph-db 而不是localhost 来连接数据库。

【讨论】:

通过在 Web 应用程序的代码中使用 graph-db:7200 有效!感谢您的解决方案。另外,我从 docker-compose.yml 中删除了网络,并留下了链接。我不知道这是否是一个好习惯。所以现在我的 Web 应用程序的代码将有 graph-db:7200 用于使用 docker 容器;但是,当我在没有 docker 容器的情况下在本地运行它时,url 中需要 localhost。当然,这是一个不同的问题,我会调查的。感谢 docker 问题的解决方案。 @zoevas 你不需要链接,这是一个在 /etc/hosts 文件中注入条目的遗留功能。当容器 IP 从重新部署/更新/缩放更改时,这不起作用。默认情况下,您将在 compose 创建的网络上获得 DNS 来解析服务名称。如果您不自己指定网络,您将看到一个名为 $project_default 的网络。 好的,我删除了链接并且仍然有效。我想这些服务可以通信,因为默认情况下它们与你所说的 $project_default 属于同一个网络。 只是一个问题,主机名定义了服务的名称对吗? 我推荐服务名称,而不是主机名。每个副本可能有一个唯一的主机名,但共享服务名和 DNS 别名。【参考方案2】:

您的数据库主机是graph-db,您应该在应用程序的数据库配置中使用该名称。例如:http://graph-db:7200

来自 docker 网络文档(桥接网络 - Docker 中的默认网络驱动程序):

想象一个具有 Web 前端和数据库后端的应用程序。 如果您调用容器 webdb,则 Web 容器可以连接 到 db 的 db 容器,无论哪个 Docker 托管应用程序 堆栈正在运行。

【讨论】:

以上是关于两个 docker 容器无法通信的主要内容,如果未能解决你的问题,请参考以下文章

Docker系列:容器之间的网络通信

Docker容器之间的通信

Nomad 连接两个 docker 容器

如何解决docker宿主机无法访问容器中的服务

无法在 localhost 上的 docker 容器之间进行通信

两个 docker 容器之间的通信问题