Docker-Compose在Linux上使用`host-gateway`模式无法连接RPC(v20.10.1)。

8
随着 Docker 20.10 的推出,Linux 平台应该可以使用 host-gateway(详见this的精彩回答)。因此,应该可以创建一个平台无关的 docker-compose 脚本。(我自己用的是 Debian。)
以下链接提供了帮助我达到目的的一些问题和答案:here, here, 和 here(连同其他答案和评论)。
我正在尝试为运行The Graph创建一个脚本,其中需要在 Docker 容器内运行 ipfs 和 postgres,并连接到 Docker 外部的区块链实例(端口为 8545)。以下是脚本内容:
 version: '3'
services:
  graph-node:
    extra_hosts:
      - "host.docker.internal:host-gateway"
    image: graphprotocol/graph-node
    ports:
      - '8000:8000'
      - '8001:8001'
      - '8020:8020'
      - '8030:8030'
      - '8040:8040'
    depends_on:
      - ipfs
      - postgres
    environment:
      postgres_host: postgres
      postgres_user: graph-node
      postgres_pass: let-me-in
      postgres_db: graph-node
      ipfs: 'ipfs:5001'
      ethereum: 'localhost:http://host.docker.internal:8545'
      RUST_LOG: info
  ipfs:
    image: ipfs/go-ipfs:v0.4.23
    ports:
      - '5001:5001'
    volumes:
      - ./data/ipfs:/data/ipfs
  postgres:
    image: postgres
    ports:
      - '5432:5432'
    command: ["postgres", "-cshared_preload_libraries=pg_stat_statements"]
    environment:
      POSTGRES_USER: graph-node
      POSTGRES_PASSWORD: let-me-in
      POSTGRES_DB: graph-node
    volumes:
      - ./data/postgres:/var/lib/postgresql/data

Docker启动正常,ipfspostgresgraph-node实例启动正常,但是graph-node的RPC调用(到区块链)全部失败,错误类似于以下内容:
WARN Trying again after eth_getBlockByNumber(0, false) RPC call failed (attempt #18) with result Err(Transport error: Error(Connect, Os { code: 111, kind: ConnectionRefused, message: "Connection refused" }))

我是否错误地使用了extra-hosts?我能做些什么来使这个脚本在我的Linux机器上工作,也能适用于Mac和Windows用户吗?

谢谢!


你解决那个问题了吗?我也遇到了同样的问题。 - Ndrslmpk
@Twixx 很遗憾,不是这样的。 - The Renaissance
1
我现在遇到了这个问题。它突然开始发生。当我 ssh 进入 graph-node docker 后,我可以轻松地 ping 到主机,但是当我添加端口 8545 来连接 chain 时,就会出现连接被拒绝的情况。我正在使用 --hostname 0.0.0.0 选项在 hardhat 节点上,所以不确定这里可能发生了什么..... - Naz
1
嗯,现在它随机工作了...看起来是硬帽节点上的--hostname 0.0.0.0选项解决了这个问题。 - Naz
2个回答

3

你的主机上运行的应用程序可能绑定到的接口与Docker使用的接口不同。

你可以使用netstat命令来检查:

$ netstat -pan | grep 8545
tcp6       0      0 127.0.0.1:8545          :::*                    LISTEN      496150/java

如果它在 127.0.0.1 上监听,就像这个例子一样,这意味着只能通过回环接口访问。
解决方案是找出 host-gateway 指向的 IP 地址,并确保服务绑定到该 IP 地址,而不是 127.0.0.1。
如果服务在所有接口上都可用(包括例如您的 WiFi 网络),那么可以绑定到 0.0.0.0,使其在所有接口上都可用。

我也遇到了这个问题,当我运行netstat命令时,在主机上看到以下内容:tcp6 0 0 :::8545 :::* LISTEN 23703/geth - Paymahn Moghadasian
1
这意味着您的服务已经在所有接口上进行监听(::是编写0.0.0.0的IPv6兼容方式),因此您不必担心我的答案所解决的问题。我知道可能会出现另一个与相同症状相匹配的问题 - 我将添加第二个答案来解决这个问题。 - Arnout Engelen

1

如果主机系统是Linux,可能您的主机防火墙规则正在应用于容器之间的通信。您可以使用sysctl检查是否存在此情况,以下设置将返回1

$ sysctl net.bridge.bridge-nf-call-arptables
1
$ sysctl net.bridge.bridge-nf-call-iptables
1
$ sysctl net.bridge.bridge-nf-call-ip6tables

您可以通过将这些值设置为“0”来修复此行为:
$ sudo sysctl net.bridge.bridge-nf-call-arptables=0
net.bridge.bridge-nf-call-arptables = 0
$ sudo sysctl net.bridge.bridge-nf-call-iptables=0
net.bridge.bridge-nf-call-iptables = 0
$ sudo sysctl net.bridge.bridge-nf-call-ip6tables=0
net.bridge.bridge-nf-call-ip6tables = 0

是的,所有这些值都是“1”。我将它们全部更改为“0”,但是当我运行容器并使用exec -it /bin/bash进入时,仍然无法连接到端口8545上的主机:root@localhost:~/code/metis/ops# docker exec -it ops_l2geth-mainnet_1 /bin/sh / # geth attach http://host.docker.internal:8545 Fatal: Failed to start the JavaScript console: api modules: Post "http://host.docker.internal:8545": context deadline exceeded。但是,如果我手动运行ufw allow 8545,那么上面的geth attach命令就可以正常工作。我正在尝试找出如何仅启用本地容器对8545的访问。 - Paymahn Moghadasian
嗯,我以为ufw会在幕后使用iptables。当你弄清楚它们如何配合时,很想听听你的看法! - Arnout Engelen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接