如何设置 docker 容器以通过主机名相互引用?

Posted

技术标签:

【中文标题】如何设置 docker 容器以通过主机名相互引用?【英文标题】:How do I set up docker containters to refer to each other by host name? 【发布时间】:2021-12-19 19:55:47 【问题描述】:

我有 2 个 docker 容器(1 个用于数据库,1 个用于应用服务器)。应用程序代码在连接字符串中有数据库的主机。我希望能够在不修改任何代码(包括连接字符串/主机配置)的情况下运行应用程序。

我的想法是在应用容器上的 /etc/hosts 文件中添加一些内容,以便数据库主机解析到另一个容器,但不确定我可以设置什么 IP 地址。每次我创建容器时,IP 都可能不同,对吗?下面的作品有点,但我需要一些更永久的东西。

172.23.0.2    database.mycompany.com

如果我可以在 /etc/hosts 中指定类似的内容会很酷

db-container-name  database.mycompany.com

编辑:很多非常有用的 cmets,但遗漏的一件事是我在代码库中有一个连接字符串,我不想更改代码:

<New class="oracle.jdbc.pool.OracleDataSource">
   <Set name="URL">jdbc:oracle:thin:@db.mycompany.com:1532:SVC</Set>
</New>

如果我想使用容器名称,我必须将上述配置更改为容器名称。我已经测试过并且它可以工作,但我无法检查它所以我需要一些不会改变代码的东西。下面提到的静态 IP 地址选项可能是我最好的选择,一旦我可以测试它就会确认答案。

【问题讨论】:

我们应该重构代码,符合twelve factors。特别是,我们应该将资源外部化。 这能回答你的问题吗? docker-compose connection between containers 谢谢诺姆。我最初在想类似的问题,问题是我仍然必须更改我不惜一切代价避免的代码库,这需要我更新连接字符串。因此,我确实想到了更改容器名称以匹配数据库主机名作为解决方法。 请记住,Stack Overflow 是一个用于编程问题的问答网站; help center 描述了此处允许的内容。如果更改代码超出范围,您的编程相关问题是什么? 【参考方案1】:

这里是示例 docker-compose.yml。

检查下面的静态 IP 分配:

version: '3.8'
services:
  nginx: <- DNS Name
    image: nginx
    container_name: qs
    restart: always
    ports:
      - 80:80
    volumes:
      - ~/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - server01
    networks:
      nginx:
        ipv4_address: 10.1.1.10 <- Static IP

networks:
  nginx:
    driver: bridge
    ipam:
      config:
        - subnet: 10.1.1.0/24 <- Static IP subnet

这样就可以消除动态IP的问题

您可以创建多个网络并根据您的连接要求进行分配。

networks:
  nginx:
    driver: bridge
    ipam:
      config:
        - subnet: 10.1.1.0/24
  db:
    driver: bridge
    ipam:
      config:
        - subnet: 10.0.0.0/24

像这里你可以看到有 2 个网络, 我如何使用它是我的应用程序容器和 nginx 在 nginx 网络上,我的 db 和应用程序在 db 网络上。所以我的客户只能通过 nginx 访问我的应用程序来访问我的数据库。并且不需要为db打开端口到主机,因为容器到容器的连接不需要打开端口。

【讨论】:

ok 也会检查该选项 这似乎是一个不错的选择,并且可能会尝试使用它。一个后续问题。我意识到我在标准 oracle 端口 1521 上创建了数据库主机,但代码实际上引用了端口 1532。您知道是否可以在同一网络上的容器之间进行端口映射,例如 1532:1521?我只是懒惰,如果需要,可以将数据库主机上的端口更新为 1532。 谢谢 - 效果很好!您的解决方案比我下面的解决方法更好,因为它为将使用 docker 映像的开发人员提供了修改主机文件并在需要时指向我们的真实数据库的选项。更改容器名称以匹配数据库主机会使这变得更加困难。 @George 用于端口映射情况,因为 1532:1521 将不起作用,因为将从您的本地主机而不是 docker 网络访问 1532 端口。在 docker 网络中,它始终只能通过端口 1521 访问。如果您不打算在 docker 网络之外远程连接到它,则不需要打开端口【参考方案2】:

您可以在同一网络中运行容器,并使用其他容器的名称来调用每个容器。

创建网络:

docker network create my-network

运行第一个容器:

docker run --name mydb -d --expose <some_port> --network=my-network mydbimage

运行将连接的第二个容器:

docker run --name myserver -d -e DB_HOST=mydb --network=my-network myserverimage

对于本示例,您可以使用 DB_HOST 环境进行连接

【讨论】:

【参考方案3】:

好的,所以我想出了一个解决方法。我可以调用我的容器 database.mycompany.com,因为 docker 会自动为每个容器名称创建 dns 映射。由于代码引用了 database.mycompany.com,因此无需更改代码即可一切正常。

【讨论】:

以上是关于如何设置 docker 容器以通过主机名相互引用?的主要内容,如果未能解决你的问题,请参考以下文章

Docker 1.10 通过主机名访问容器

在 Elastic Beanstalk 上设置 Docker 容器主机名

如何通过“主机名”在 Docker 容器之间进行通信

docker桥接模式

docker——端口映射与容器互联

Docker容器学习梳理--容器间网络通信设置(Pipework和Open vSwitch)