Docker容器通过localhost无法访问,但可以通过127.0.0.1访问。

6

问题

我有一个 Docker 服务容器,它的端口为 *:8080

  • 我无法通过 localhost:8080 访问容器。使用 Chrome 或者 curl 时会一直卡住。
  • 但是如果我使用其他本地IP,例如127.0.0.1,就可以访问容器。

这让我很困惑,因为在我的 hosts 文件中,localhost 被重定向到 127.0.0.1

为什么会这样?这与IPv4/IPv6双栈有关系吗?

环境

我正在使用基于 Ubuntu 的 PopOS,并启用了 Docker Swarm。 我使用此测试堆栈文件:traefik.docker-compose.yml

version: '3'
services:
  reverse-proxy:
    image: traefik # The official Traefik docker image
    command: --api --docker # Enables the web UI and tells Traefik to listen to docker
    ports:
      - "80:80"     # The HTTP port
      - "8080:8080" # The Web UI (enabled by --api)
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock # So that Traefik can listen to the Docker events

为了运行堆栈,我使用:
docker stack deploy -c traefik.docker-compose.yml traefik

一旦服务启动,我确认它通过以下两种方式监听 8080 端口:

  1. docker service ls
ID                  NAME                    MODE                REPLICAS            IMAGE               PORTS
4ejfsvenij3p        traefik_reverse-proxy   replicated          1/1                 traefik:latest      *:80->80/tcp, *:8080->8080/tcp
  1. sudo ss -pnlt | grep 8080
LISTEN   3         128                       *:8080                   *:*        users:(("dockerd",pid=2119,fd=45))

供参考,这是我 /etc/hosts 的内容:


127.0.0.1   localhost
::1     localhost ipv6-localhost
127.0.1.1   pop-os.localdomain  pop-os pop1810x220

我只是用 curl 进行测试:

  • 可以使用: curl http://127.0.0.1:8080
  • 会卡住不动: curl http://localhost:8080

curl 'http://[::1]:8080'(IPv6版的localhost)怎么样? - Charles Duffy
1
这实际上是我所希望的 - 它告诉我们localhost出了什么问题。请记住,/etc/hosts不是名称解析中唯一涉及的部分 - 您需要评估系统的NSS模块以了解所有组件的作用,因此您不能相信/etc/hosts会覆盖所有其他内容而不调查您的发行版(或本地覆盖的系统管理员)如何设置名称解析。 - Charles Duffy
这为调查开辟了新的途径,我会更深入地挖掘,谢谢! - Jeric de Leon
1
你找到解决方案了吗? - p0rter
我遇到了相同的问题。然而,使用 docker run 部署的容器在访问 ::1 时工作正常。使用 docker compose 或 swarm 部署的容器无法将外部 ipv6 映射到 ipv4。如果你查看 netstats -tulpn,就会发现正常的容器是通过 docker-proxy 监听的,而 swarm 则是通过 dockerd 监听的。我不确定这是什么原因导致的差异。希望能有更新解决方案。 - Yuanyi Wu
显示剩余2条评论
1个回答

0

尝试在运行的容器中编辑 /etc/hosts,以删除第二个“localhost”引用,该引用位于第二行,并在“::1”之后的几个空格后,使其读取如下:

::1 ipv6-localhost


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