【问题标题】:Cannot access HTTP from inside Docker container on bridge network无法从桥接网络上的 Docker 容器内部访问 HTTP
【发布时间】:2023-03-03 02:07:01
【问题描述】:

我的开发环境是在 Vagrant (VirtualBox) Linux 服务器上运行 MySQL(端口 3306)和 Tomcat(端口 18080)。这是我运行 Docker 的主机服务器。

我需要在 docker 内运行另一个服务,该服务连接到主机上的 MySQL 和 Tomcat 服务器以及任何外部 Web 服务器。

我发现到主机的 MySQL 连接很好。但是,与 HTTP(端口 80 或 443)的连接将超时。如果我在我的 Mac 上运行相同的 Docker 映像(在 Vagrant 之外),我可以连接到 MySQL 和任何外部 Web 服务器)。

详情如下:

在我的主机上(Vagrant)

[root@my Downloads]# ip addr show docker0
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:95:b0:5e:47 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.1/24 brd 192.168.100.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:95ff:feb0:5e47/64 scope link 
       valid_lft forever preferred_lft forever
[root@my Downloads]# 

我进入 Docker 并尝试连接到主机的 MySQL。这很好用。

[root@my Downloads]# docker exec -it myDocker sh
/opt/myDocker # nc 192.168.100.1 3306
Q
5.7.26-29-logf"}1
                 Q&
                   ??S???&z GTP[a{mysql_native_passwordasdasd
!??#08S01Got packets out of order^Cpunt!

/opt/myDocker # 

但如果我尝试连接到 HTTP,它就不起作用。

/opt/myDocker # nc 192.168.100.1 18080
/opt/myDocker # nc www.google.com 80
GET /
/opt/myDocker # GET /
sh: GET: not found
/opt/myDocker # 

在 18080 上连接到我的主机的 Tomcat 将返回提示。到 google.com 的那个会挂在那里一段时间,然后返回提示。

我在主机(Vagrant VM)上尝试了https://docs.docker.com/network/bridge/ 中提到的以下方法,但没有帮助。

sysctl net.ipv4.conf.all.forwarding=1
iptables -P FORWARD ACCEPT

我没有想法。有人可以帮忙吗?

编辑 1: 我认为这一定与桥接网络有关。我在同一个虚拟机上尝试了另一个带有主机网络的 docker,它很好。

/dokcer2 # nc 192.168.100.1 18080
GET /



<!DOCTYPE html >
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <link rel="shortcut icon" href="/auth/images/favicon.ico?v=13"/>
    <link rel="stylesheet" type="text/css" href="/auth/static/styles/main.a7589877fc3cc07b7ac7.css"/>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="loginAppRoot"></div>
<script type="text/javascript" src="/auth/static/js/main.f5071db7f71c2283a0f9.js"></script>
</body>
</html>^Cpunt!

/docker2 # nc www.google.com 80
GET /
HTTP/1.0 200 OK
Date: Sun, 15 Nov 2020 05:21:20 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=ISO-8859-1
... yada yada yada redacted ...

【问题讨论】:

  • 可能的原因:1.linux防火墙,2.启用selinux,3.没有在容器外转发端口,4.tomcat监听不同的端口,5,virtualbox网络设置等等等等等等。而且,实际上,我无法清楚地理解什么是连接的来源和目的地。
  • 谢谢@rzlvmp。我应该提到我尝试了 1、2、4 和 5。它们都检查得很好。查看我在具有主机网络的同一个 Vagrant 上的另一个 docker 实例上的编辑。至于您的第 3 点。没有在容器外转发端口,有什么指示如何检查吗?
  • 你手动设置了192.168.100.1吗?您确定此 IP 尚未被网络路由器使用吗?而你的本地网络是 192.168.100.0/24?
  • 我没有手动设置192.168.100.1。它已经在我的流浪者身上了。我通过运行ip addr show docker0 命令得到它。此外,该 IP 仅对我的 Vagrant 是本地的。它在 Vagrant 之外无法访问。我的本地网络(从 Vagrant 的角度来看)是 10.0.2.0/24。 vagrant 外的本地网络是 192.168.0.0/24。

标签: docker networking vagrant


【解决方案1】:
  1. 好的,首先我建议您更好地了解 docker 网络(以及所有网络)

Docker network overview

Docker bridge networks

Binding container ports

  1. 在你的情况下:

虚拟机的内网是10.0.2.0/24(带桥接接口10.0.2.1)
Docker内网为192.168.100.0/24(带桥接接口192.168.100.1)

当您尝试连接到虚拟机时,您使用的是 10.0.2.11,而不是 10.0.2.1(即网桥接口)
Docker 的网络也是一样的。您无法直接通过 192.168.100.1 访问 192.168.100.11 的容器,因为您无法从 192.168.0.X 访问 10.0.2.1。
您需要将端口从 192.168.100.0/24 绑定(转发)到 10.0.2.0/24 并通过 10.0.2.X 访问您的服务。
如何绑定端口?见Binding container ports链接
Docker 的内部网络(我的图片中的浅蓝色)仅用于 Docker。

【讨论】:

  • 感谢您提供的图表。令我困惑的是,在 VM1 上,除了 docker 之外,我还运行了 MySQL 服务器(不是在 docker 上,而是在标准守护程序上)和一个 Java Spring 应用程序(也不是在 docker 上)。因此,让我们添加 2 个框,分别代表上图 VM1 上端口 3306 和 18080 上运行的服务。我不明白的是,为什么从 container1 我可以连接到 192.168.100.1 端口 3306 但我不能连接到同一个 192.168.100.1 端口 18080。要明确的是,问题是从容器内部向外部提供服务,而不是暴露内部服务到外部使用端口映射等。
  • 顺便说一句,你的图表是正确的。这正是网络拓扑的样子。
  • 没有细节我不能说更多。也许mysql监听所有ips(0.0.0.0),但java只有10.0.2.X。无论如何,直接使用 docker bridge interface ip 不是标准方式,特别是如果您的服务不在容器内。
猜你喜欢
  • 1970-01-01
  • 2018-12-09
  • 2020-06-06
  • 2018-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-07
  • 1970-01-01
相关资源
最近更新 更多