【问题标题】:Docker containers are not able to see each other in docker compose, nor is hostDocker 容器在 docker compose 中无法看到彼此,主机也无法看到
【发布时间】:2019-12-08 05:10:51
【问题描述】:

我在使用 Docker 时遇到了几个问题。

  1. 主机 (Windows 10) 无法访问容器托管的任何资源。
  2. 容器本身也无法看到彼此。

我的配置:

version: '3.7'
services:
  chrome:
    build: ./chrome
    container_name: chrome_container
    ports:
      - "9223:9223"

  dotnetapp:
    depends_on:
       - chrome
    build: ./dotnetapp
    container_name: live_container
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
    stdin_open: true
    tty: true

Dockerfile 用于 chrome(它所做的一切 - 启动 Chrome 并进行调试,在端口 9223 上启用):

FROM debian:buster-slim

# preparation
RUN apt-get update; apt-get clean
RUN apt-get install -y wget
RUN apt-get install -y gnupg2

# installing xvfb
RUN apt-get install -y xvfb

# installing Chrome
RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
RUN apt-get update && apt-get install -y google-chrome-beta

EXPOSE 9223

COPY ./docker-entrypoint.sh /usr/local/bin/
RUN ln -s usr/local/bin/docker-entrypoint.sh / # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["test"]

docker-entrypoint.sh

#!/bin/bash
set -e

if [ "$1" = 'test' ]; then
    rm -f /tmp/.X99-lock
fi

xvfb-run -e /dev/stdout --server-args='-screen 0, 2560x1440x16' google-chrome --window-size=2560,1440 --no-sandbox --remote-debugging-port=9223 --user-data-dir=remote-profile https://www.google.com/

Dockerfile 用于第二个应用程序(仅用于 docker 内部网络测试)

FROM mcr.microsoft.com/dotnet/core/runtime:2.2

# run app
CMD ["/bin/bash"]

所以,现在,详细说明第 1 点:

我可以通过运行:docker-compose up --build chrome 来启动 chrome 容器。

然后,在主机系统上,我尝试打开浏览器 localhost:9223http://172.17.0.2:9223/,在这两种情况下,我都会收到“无法访问页面错误”。附:我从docker inspect 命令获得了IP。

另一方面,如果我尝试进入正在运行的容器docker exec -it chrome_container bash 并执行命令curl localhost:9223,那么它会显示成功结果。

此时,如果我尝试使用其他地址,例如 curl chrome:9223curl http://chrome:9223curl chrome_container:9223curl http://chrome_container:9223,那么它们也会失败。根据文档 - 内部网络中的所有容器都应为accessible by the service host name。在我的场景中,这完全是错误的。

我也尝试不依赖docker compose 像这样docker run -p 9223:9223 -it --rm all_chrome 启动图像,但结果是一样的。该资源在主机系统中不可用。

现在,详细说明问题 2。

当我像这样docker-compose up 运行这两个应用程序时。并通过docker exec -it live_container bash 登录第二个应用程序。然后尝试使用上述 URL 访问第一个容器 - 所有这些都失败(curl localhost:9223curl 0.0.0.0:9223curl chrome:9223curl http://chrome:9223curl chrome_container:9223curl http://chrome_container:9223)。

我尝试了几次重新启动 Docker 并尝试了不同的端口。我怎样才能弄清楚这些事情?

  1. 如何访问主机系统9223端口的资源?

  2. 为什么第二个服务不能使用主机名看到第一个服务,如文档中的here

我在 Windows 10 上使用 Docker。

编辑:更多细节。

  • 通过 localhost 访问时 - 显示以下错误:

  • 通过 IP 访问时显示以下错误:

所以在主机系统(win 10)上通过 localhost 访问时似乎发生了一些事情。

【问题讨论】:

  • 运行独立容器时docker container ps -a 会显示什么?
  • @michalk 这是输出:CONTAINER ID (51b90eefcf91), IMAGE (all_chrome), COMMAND ("docker-entrypoint.s…" ), CREATED ( About a minute ago), STATUS (Up About a minute), PORTS (0.0.0.0:9223->9223/tcp), NAMES (naughty_boyd)。使用命令启动:docker run -p 9223:9223 -it --rm all_chrome。更多细节。当我尝试使用 localhost:9223 访问资源时 - 错误是:This page isn’t working. localhost didn’t send any data. ERR_EMPTY_RESPONSE。当我使用 IP 时:This site can’t be reached 172.17.0.2 took too long to respond..
  • @michalk 我在问题底部添加了 2 个屏幕截图。请看一看。
  • @michalk 找到了解决方案!
  • 很好,请考虑为您自己的问题添加答案以供将来参考。

标签: docker curl docker-compose


【解决方案1】:

刚刚在topic 中发现了信息,即Chrome 在调试模式下根本不接受来自本地主机network 之外的连接。

因此,将容器启动为:

docker run -p 5656:5656 -it --rm all_chrome

然后为了解决这个问题,我必须使用代理。这是一个例子:

socat tcp-listen:5656,fork tcp:localhost:9223

之后 - 通过 localhost 访问可以正常工作:

我还没有弄清楚如何在守护进程模式下启动socat,所以我可以让它成为docker 中启动脚本的一部分。但这是一件小事。

编辑。几个笔记。

从另一个容器访问 Chrome 容器

如果您尝试使用该 IP 从另一个容器访问调试会话,那将可以正常工作:

curl 172.19.0.2:5656

否则,如果您尝试使用主机名 - 您会看到错误。

curl chrome:5656

错误:

主机标头已指定且不是 IP 地址或 localhost.root@38f2b5fa34ca:/app# curl chrome:5656

这可以通过剥离Host 标头值来解决:

curl chrome:5656 -H 'Host: '

问题仍然是这不是很方便的方法。因为应用程序并不总是有可能从请求中删除标头。例如 - chromedriver。因此,一个解决方案是在 chrome docker 容器上进行配置,这将删除所有传入请求的 Host 标头值。我尝试使用 squid 代理,但没有成功。所以,相反,我想出了另一个解决方案。

解决方案是为容器的内部网络使用静态、固定的 IP 地址。这样 - 您始终可以确保 docker 将使用相同的地址,因此您的应用程序可以在调用中使用它。

配置如下:

version: '3.7'
services:
  chrome:
    networks:
        front:
            ipv4_address: 172.16.238.5 
  app2:
    networks:
        front:
            ipv4_address: 172.16.238.10 
networks:
  front:
    driver: bridge
    ipam:
     config:
       - subnet: 172.16.238.0/24

现在在 app2 中您可以使用固定 IP 拨打电话:

CURL 172.16.238.5:5656

这是迄今为止最简单的解决方案..

附言如果您在无头模式下运行 chrome,那么您可以提供额外的参数,理论上可以解决您的一些问题--remote-debugging-address。试试吧。

【讨论】: