Linux 上的 docker-compose `host-gateway` 无法连接到 RPC (v20.10.1)

Posted

技术标签:

【中文标题】Linux 上的 docker-compose `host-gateway` 无法连接到 RPC (v20.10.1)【英文标题】:docker-compose `host-gateway` on Linux cannot connect to RPC (v20.10.1) 【发布时间】:2021-04-06 08:09:38 【问题描述】:

随着 Docker 20.10 的出现,host-gateway 应该可以在 Linux 平台上使用(详见 this 精彩回答)。因此,应该可以创建一个与平台无关的docker-compose 脚本。 (我自己在 Debian 上。)

这里有一些问题和答案的链接,这些链接有助于我走到这一步:here、here 和 here(以及其他一些答案和 cmets)

我正在尝试创建一个用于运行 The Graph 的脚本,其中包括在 Docker 容器内运行 ipfspostgres,并连接到 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 用户上运行?

谢谢!

【问题讨论】:

您找到解决该问题的方法了吗?我有同样的问题.. @Twixx 很遗憾没有 我现在遇到了这个问题。它只是随机开始发生。当我 ssh 进入图形节点泊坞窗时,我可以毫无问题地 ping 到主机,但是一旦我添加端口 8545 以连接到链,我就会被拒绝连接。我在安全帽节点上使用 --hostname 0.0.0.0 选项,所以不确定这里会发生什么...... 嗯,现在它随机工作了......似乎是安全帽节点上的 --hostname 0.0.0.0 选项修复了它。 【参考方案1】:

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

您可以通过netstat查看:

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

如果它正在监听127.0.0.1,就像在这个例子中,这意味着它只能通过环回接口访问。

解决方案是找出主机网关指向的 IP 地址,并确保服务绑定到该 IP 地址而不是 127.0.0.1。

如果该服务在所有接口上都可用(包括例如您的 wifi 网络)没有问题,您可以绑定到0.0.0.0 使其在所有接口上可用。

【讨论】:

我也遇到了这个问题,当我运行netstat 命令时,我在主机上看到以下内容:tcp6 0 0 :::8545 :::* LISTEN 23703/geth 这意味着您的服务已经在监听所有接口(@98​​7654327@ 是与 IPv6 兼容的写法0.0.0.0),所以您没有我的答案就是解决方案的问题.不过,我知道另一个可能与相同症状相匹配的问题 - 我将对此添加第二个答案。【参考方案2】:

如果主机系统是 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 嗯,我以为 ufw 会在后台使用 iptables。当您弄清楚时,会很想知道它是如何组合在一起的!

以上是关于Linux 上的 docker-compose `host-gateway` 无法连接到 RPC (v20.10.1)的主要内容,如果未能解决你的问题,请参考以下文章

了解 Docker/Docker-Compose 上的 Gunicorn 和 Flask

Docker-compose 在 M1 mac 上的 VM (Parallels) 中

node_modules 上的 docker-compose 卷但为空

Linux企业运维——Docker三剑客之docker-compose

docker-compose ECONNREFUSED 用于 nodeJS 上的 Postgres

Docker Compose (docker-compose) 无法连接到 Windows Server 2016 TP5 上的 docker 守护进程