揭开 `172.17.0.1` 的神秘面纱

29 1123

前言

哈喽,大家好,我是你们的小小~ 👋

最近在社区里,有很多同学问了我一个看似非常基础、却又暗藏玄机的问题:“小小学姐,我的原始笔记里只记下了一个神秘的 IP 地址 —— 172.17.0.1。当时我发现在 Docker 容器里,只要访问 172.17.0.1:3000,竟然就能神奇地穿透容器,直接访问到我宿主机上的 3000 端口!这到底是怎么做到的?

很多初学 Docker 的同学,可能都把 172.17.0.1 当作一个“魔法咒语”来背诵。遇到容器需要连宿主机的数据库(比如 MySQL、Redis),直接写上这个 IP 就能跑通,于是大呼“Docker 真香”,却很少有人真正停下来问一句:为什么?

作为一名技术人,“知其然,更要知其所以然”。比喻只是我们理解框架的拐杖,真正的目的地永远是底层那精密咬合的运行原理。如果仅仅停留在“会用”的层面,当有一天你换了 Mac 系统、或者公司网络网段冲突、又或者宿主机服务报错 Connection refused 时,你就会陷入深深的绝望。

今天,小小就带你进行一场 “硬核但不枯燥” 的深度技术探秘。我们将从这区区 10 个字符的 172.17.0.1 出发,像剥洋葱一样,一层一层地撕开 Docker 网络架构的面纱。

无论你是刚接触 Docker 的小白,还是想要彻底吃透底层机制、提升技术壁垒的资深大牛,这篇文章都将为你构建一个完整、严密的 Docker 容器网络知识闭环。

准备好了吗?泡杯咖啡,我们发车!🚀


🔥 揭开 172.17.0.1 的神秘面纱:万字长文吃透 Docker 容器与宿主机通信底层原理


🧭 导览 (Table of Contents)

  1. 🌟 现象与谜题:为什么 172.17.0.1 成了“穿墙术”?
  2. 🧱 筑基篇:Docker 网络的“三大法宝”
    • 法宝一:Network Namespace(网络命名空间)—— 平行宇宙的结界
    • 法宝二:Linux Bridge(虚拟网桥 docker0)—— 连接宇宙的星际空间站
    • 法宝三:veth pair(虚拟以太网对)—— 跨越结界的隐形网线
  3. 🗺️ 核心探秘:揭秘 172.17.0.1 的真实身份
  4. 🛣️ 动态追踪:一个数据包的“奇幻漂流” (附详细流转图)
  5. ⚠️ 致命踩坑指南:为什么 IP 对了,却还是 Connection refused
    • 深入理解 0.0.0.0 vs 127.0.0.1 Socket 绑定机制
  6. 🧠 大牛进阶:剥开 iptables 与内核路由的硬核外衣
    • 内核路由表的秘密
    • Docker 是如何悄悄修改 iptables NAT 表的?
  7. 💣 跨平台噩梦:Mac 和 Windows 玩家的专属“深坑”
    • 为什么 172.17.0.1 在 Mac/Windows 下突然失效了?
    • 终极解决方案:host.docker.internal 解析
  8. 💡 小小的最佳实践与架构建议
  9. 🙋 高频 Q&A (疑难杂症专诊)
  10. 🎓 总结

1. 🌟 现象与谜题:为什么 172.17.0.1 成了“穿墙术”?

在讲枯燥的原理前,我们先还原一个最经典的真实开发场景。

假设你在自己的电脑(宿主机)上跑了一个 Node.js Web 服务或者 MySQL 数据库,监听在 3000 端口。
接着,你启动了一个 Docker 容器(比如一个 Nginx 容器),你想在这个容器里面,把请求转发或者连接到宿主机的 3000 端口。

❌ 新手的直觉错误:
你会想当然地在容器配置里写:localhost:3000127.0.0.1:3000
结果: 报错!连接失败。因为在容器的“平行宇宙”里,它的 127.0.0.1 指的是容器自己,而不是宿主机。容器自己并没有监听 3000 端口。

✅ 老鸟的魔法代码:
你向公司的资深大佬求助,大佬轻描淡写地丢来一句:“把 127.0.0.1 换成 172.17.0.1 试试。”
你半信半疑地改掉,重启容器——结果: 竟然奇迹般地通了!

为什么这串数字有这种魔力?它究竟指向哪里?要回答这个问题,我们必须下沉到 Linux 的网络底层。


2. 🧱 筑基篇:Docker 网络的“三大法宝”

Docker 并不是什么魔法,它的本质是对 Linux 内核特性的高级封装。要弄懂 172.17.0.1,必须先掌握构建 Docker 网络世界的三个底层基石

🛡️ 法宝一:Network Namespace(网络命名空间)—— 平行宇宙的结界

Linux 提供了一种名为 Namespace(命名空间) 的内核隔离机制。其中 Network Namespace 专门用于隔离网络资源。

  • 概念白话: 想象宿主机的网络是一个繁华的“主宇宙”,拥有网卡(eth0)、IP、路由表和端口空间。当 Docker 启动一个容器时,它会利用 Network Namespace 为这个容器创造一个绝对隔离的“平行宇宙”。
  • 特性: 在这个平行宇宙里,容器拥有自己独立的虚拟网卡、独立的 IP 地址、独立的路由表,甚至 独立的 端口号空间(这就是为什么你在不同容器里都可以监听 80 端口而不冲突的原因)。

🛸 法宝二:Linux Bridge(虚拟网桥 docker0)—— 连接宇宙的星际空间站

平行宇宙之间是无法直接通信的,容器既不能上网,也不能跟宿主机说话。这显然不行。于是,Docker 在宿主机的“主宇宙”中,建造了一个“星际空间站”——虚拟网桥(Linux Bridge)

当你安装并启动 Docker 服务时,Docker 会自动在宿主机上创建一个名为 docker0 的虚拟网桥。

  • 本质: 网桥(Bridge)在网络协议栈中工作在数据链路层(L2),你可以把它通俗地理解为一台虚拟交换机(Virtual Switch)
  • 神仙操作: Docker 不仅建了这台交换机,还给这台交换机分配了一个 IP 地址!默认情况下,这个 IP 就是 172.17.0.1

📌 划重点:docker0 网桥是存在于宿主机网络空间中的。因此,172.17.0.1 这个 IP,实质上是宿主机自己网络栈上的一个 IP 地址!

🧵 法宝三:veth pair(虚拟以太网对)—— 跨越结界的隐形网线

现在我们有了孤立的容器,有了宿主机上的 docker0 交换机。怎么把它们连起来呢?Linux 内核提供了第三个法宝:veth pair(Virtual Ethernet Pair)

  • 特性: veth pair 永远是成对出现的,它们就像是一根无形的网线。从这一头发送的数据包,会原封不动地从另一头出来。
  • Docker 的连接魔法:
    1. Docker 把这根“网线”的一头插在容器的“平行宇宙”里,命名为 eth0(容器内的虚拟网卡),并给它分配一个同网段的 IP(比如 172.17.0.2)。
    2. Docker 把这根“网线”的另一头穿透结界,插在宿主机的 docker0 虚拟交换机上(通常命名为 vethXXXX 这样的随机乱码网卡)。

💡 小结图景: 现在,所有容器都通过自己的“网线”插在了 docker0 这台交换机上。而这台交换机本身的 IP,就是 172.17.0.1


3. 🗺️ 核心探秘:揭秘 172.17.0.1 的真实身份

经过前面的筑基,我们现在可以正式给 172.17.0.1 下个定义了。

在默认的 bridge 网络模式下,172.17.0.1 拥有双重身份:

  1. 对于宿主机而言: 它是宿主机上一张名为 docker0 的虚拟网卡的 IP 地址。只要宿主机网络不瘫痪,宿主机始终认领这个 IP。
  2. 对于容器而言: 它是容器通向外部世界的 默认网关(Default Gateway)

我们可以通过进入容器内部,查看路由表来验证这一点:

# 进入一个正在运行的容器(假设为 Nginx 容器)
$ docker exec -it my_nginx /bin/sh

# 在容器内查看路由表
$ ip route

容器内的输出结果:

default via 172.17.0.1 dev eth0 
172.17.0.0/16 dev eth0 scope link  src 172.17.0.2 

🧠 原理解密:
第一行 default via 172.17.0.1 dev eth0 明确宣告了:“对于我不认识的 IP(除了 172.17.x.x 同网段的局域网),通通把数据包从 eth0 网卡丢出去,交给网关 172.17.0.1 处理!”

因为 172.17.0.1 实实在在是绑定在宿主机的内核中的,所以,容器向 172.17.0.1 发送网络请求,实际上就是直接把请求发送给了宿主机本身! 这就是为什么它能“指向宿主机端口”的根本原因。


4. 🛣️ 动态追踪:一个数据包的“奇幻漂流”

为了让初学者建立直观的、极具画面感的理解,我们用 Mermaid 图表来展示当容器执行 curl 172.17.0.1:3000 时,数据包经历了怎样的一生。

sequenceDiagram
    participant Container as 容器 (IP: 172.17.0.2)
    participant Veth as veth pair (隐形网线)
    participant Docker0 as 宿主机 docker0 (IP: 172.17.0.1)
    participant HostOS as 宿主机操作系统网络栈
    participant HostApp as 宿主机 Node 服务 (Port: 3000)

    Note over Container: 执行 curl 172.17.0.1:3000
    
    Container->>Container: 1. 查路由表:目标IP不是本地<br>将数据发往默认网关 172.17.0.1
    Container->>Veth: 2. 数据包通过容器内 eth0 发出
    Veth->>Docker0: 3. 数据包瞬间到达宿主机的另一端
    Docker0->>HostOS: 4. 宿主机内核收到以 172.17.0.1 为目标的包
    HostOS->>HostOS: 5. 发现目标 IP 是自己管理的 docker0 接口!
    HostOS->>HostApp: 6. 查找是否有进程监听 3000 端口,发现 Node 服务并转交
    Note over HostApp: 7. Node 服务处理请求并原路返回响应

详细文字拆解:

  1. 寻路: 容器内程序试图访问 172.17.0.1,查自己的路由表,发现该发往网关。
  2. 出舱: 数据包从容器内的 eth0 虚拟网卡发出。
  3. 穿隧: 经过 veth pair 隧道,数据包立刻到达宿主机侧的 docker0 网桥。
  4. 宿主机接管: 宿主机的 Linux 内核网络协议栈拦截到这个数据包。内核检查数据包的目标 IP,发现 172.17.0.1 刚好是自己身上的一个网卡 IP(docker0),于是内核拍板:“哦,这包是发给我的!
  5. 端口匹配: 内核剥离 IP 层,查看 TCP/UDP 传输层,发现目标端口是 3000。于是内核向系统内广播:“谁监听了 3000 端口?”
  6. 建立连接: 你跑在宿主机上的服务站出来接管了这个连接,通信成功!

5. ⚠️ 致命踩坑指南:为什么 IP 对了,却还是 Connection refused

很多同学看到这里,觉得已经天下无敌了。转身去公司服务器上试:容器内 curl 172.17.0.1:3000
结果现实给你泼了一盆冷水:

curl: (7) Failed to connect to 172.17.0.1 port 3000: Connection refused

“小小骗人!原理解释得天花乱坠,为什么我连不上?被拒绝了!”

别急,这也是 90% 的新手必定会踩的惊天巨坑!这个锅 Docker 不背,要怪就怪宿主机服务的“绑定地址(Bind Address)”

🕵️ 深入理解 Socket 绑定机制(0.0.0.0 vs 127.0.0.1

任何一个后端服务(如 Node.js, Spring Boot, MySQL, Redis)在启动监听端口时,都需要提供两个要素:端口号绑定的 IP 地址

很多现代开发框架和数据库(出于安全考虑),默认绑定的 IP 地址都是 127.0.0.1localhost

  • 如果宿主机服务监听在 127.0.0.1:3000
    这意味着该服务非常傲娇,它告诉宿主机的操作系统:“我只接客从本地回环网卡(lo 网卡,即 127.0.0.1)进来的请求!外部网络,包括其他网卡进来的,一律给我拒之门外!
    还记得刚才的《奇幻漂流》吗?容器发来的请求,是从 docker0 网卡 进来的,目标 IP 是 172.17.0.1
    所以,哪怕请求成功到达了宿主机内核,内核一核对:服务只认 127.0.0.1,但你的包是冲着 172.17.0.1 来的,不匹配,直接拒绝连接 (Connection refused)!

  • 如果宿主机服务监听在 0.0.0.0:3000
    0.0.0.0 在网络中代表一个特殊含义:“绑定本机所有可用的 IP 地址”
    也就是告诉内核:“不管是物理网卡(192.168.x.x)、回环网卡(127.0.0.1)还是虚拟网卡 docker0(172.17.0.1)进来的 3000 端口请求,老子全包了!”
    这样,容器通过 172.17.0.1 发过来的请求,就能被顺利接收。

🛠️ 避坑解决方案

当你遇到容器无法访问宿主机特定端口时,第一步,请务必在宿主机上执行:

netstat -tlnp | grep 3000
# 或者
ss -tlnp | grep 3000
  • ❌ 错误状态: tcp 0 0 127.0.0.1:3000 0.0.0.0:* LISTEN
  • ✅ 正确状态: tcp 0 0 0.0.0.0:3000 0.0.0.0:* LISTEN (或者 :::3000)

如何修复?修改宿主机服务的配置!

  • Node.js / Express: app.listen(3000, '0.0.0.0')
  • MySQL: 编辑 my.cnf,将 bind-address = 127.0.0.1 改为 bind-address = 0.0.0.0
  • Redis: 编辑 redis.conf,将 bind 127.0.0.1 改为 bind 0.0.0.0 或直接注释掉。
  • (修改后记得重启对应的宿主机服务)

6. 🧠 大牛进阶:剥开 iptables 与内核路由的硬核外衣

📌 小小提示: 这一章节主要为有一定网络基础的进阶读者准备。小白如果看不懂没关系,可以直接跳到第 7 节。但如果你想成为团队里的 Docker 救火队长,这里的原理必须死磕下来。

前文我们提到了“网桥”、“网关”,这仅仅是第一层。Docker 之所以能在 Linux 上如鱼得水,其幕后的终极黑手其实是:Linux iptables(Netfilter)防火墙规则

当容器不仅仅是访问宿主机,而是要通过宿主机访问外网(比如去拉取 Github 的代码),或者外部网络要访问容器(比如 -p 8080:80),单靠 docker0 是不够的,必须依赖 iptables 进行网络地址转换(NAT)。

🔍 Docker 对 iptables 做了什么手脚?

只要你启动了 Docker 服务,Docker Daemon 就会极其霸道地接管你宿主机内核的 iptables,向里面注入大量私有规则。我们可以通过宿主机的终端查看:

sudo iptables -t nat -L -n

你会看到几条极其关键的规则链(Chains):

1. SNAT(源地址转换)与 MASQUERADE

当容器(172.17.0.2)试图访问外网(比如 8.8.8.8)时,数据包来到宿主机的 docker0 网关。如果宿主机直接把带有源 IP 172.17.0.2 的包发到公网上,公网路由器会直接丢弃(因为 172.17.x.x 是私有网段,不能在公网路由)。

Docker 写入了类似这样的规则:

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0

原理: MASQUERADE(伪装)。当 172.17.x.x 网段的数据包即将离开宿主机(POSTROUTING 阶段)时,宿主机内核会自动将数据包的 源 IP 篡改为宿主机自己的物理网卡 IP(例如 192.168.1.100)。外网响应回来时,宿主机内核再聪明地把目标 IP 翻译回容器的 IP。
这叫做 SNAT (Source Network Address Translation)

2. DNAT(目标地址转换)与端口映射 (-p)

我们常写 docker run -p 8080:80 nginx。为什么访问宿主机的 8080 端口,就能神奇地打入容器内部的 80 端口?
这是因为 Docker 在 PREROUTINGDOCKER 链中写了规则:

Chain DOCKER (2 references)
target     prot opt source               destination         
DNAT       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:8080 to:172.17.0.2:80

原理: 当外部请求访问宿主机的 8080 端口时,宿主机内核在数据包刚刚到达(PREROUTING 阶段)时,直接拦截,将数据包的 目标 IP 和目标端口 强行篡改为容器的 IP 172.17.0.2 和端口 80。然后数据包被丢进 docker0 网桥,顺着 veth pair 掉进了容器里。
这叫做 DNAT (Destination Network Address Translation)


7. 💣 跨平台噩梦:Mac 和 Windows 玩家的专属“深坑”

好了,在 Linux 下,172.17.0.1 的底层逻辑已经无懈可击了。
但是!如果你的开发机器是 MacBook 或者 Windows,你会发现前面讲的这些,在你的机器上全部 失!效!了!

你在 Mac 的 Docker 容器里 curl 172.17.0.1:3000,绝对是超时(Timeout)或者无响应。

为什么呢?这难道是玄学?

🧐 揭穿 Docker Desktop 的谎言:多了一层“虚拟机”!

我们必须要知道一个扎心的残酷事实:Docker 容器的核心本质是依赖于 Linux 内核特性的(Namespace, Cgroups)。Mac OS (Darwin) 和 Windows (NT) 的内核根本没有这些东西!

那怎么能在 Mac/Windows 上跑 Docker 呢?
真相大白: 当你安装 Docker Desktop for Mac/Win 时,它其实是在你的系统里偷偷启动了一个极其轻量级的 Linux 虚拟机(VM / Hypervisor)!所有的容器,都跑在这个不可见的虚拟机里面。

我们来看这幅残酷的架构对比图:

graph TD
    subgraph Linux 原生环境
        L_Host[宿主机 Host OS]
        L_Docker0[docker0: 172.17.0.1]
        L_Container[容器: 172.17.0.2]
        
        L_Host --- L_Docker0
        L_Docker0 --- L_Container
    end

    subgraph "Mac / Windows 桌面版 Docker (Docker Desktop)"
        M_Host[你的电脑 Mac/Win Host]
        
        subgraph 隐藏的 Linux VM
            M_Docker0[docker0: 172.17.0.1]
            M_Container[容器: 172.17.0.2]
        end
        
        M_Host -.隔离.- M_Docker0
        M_Docker0 --- M_Container
    end
    
    style L_Host fill:#f9f,stroke:#333,stroke-width:4px
    style M_Host fill:#f9f,stroke:#333,stroke-width:4px
    style 隐藏的 Linux VM fill:#ccf,stroke:#333,stroke-width:2px,stroke-dasharray: 5 5

致命断层分析:
在 Mac/Win 上,那个大家熟悉的 docker0 网桥(172.17.0.1),是存在于那台隐藏的 Linux 虚拟机内部的!
并不在你的 Mac/Windows 宿主机上!

所以,当容器在 Mac 环境下请求 172.17.0.1:3000 时,请求抵达了那台虚拟机的内核,然后虚拟机内核一看:“我身上没有进程监听 3000 端口啊。”(因为你的 Node/MySQL 是跑在 Mac 的操作系统上的,而不是虚拟机里)。于是,请求石沉大海。

🚀 终极解决大招:host.docker.internal

为了解决这种跨平台的网络割裂,Docker Desktop 官方提供了一个非常优雅、跨时代的魔法 DNS 域名:
👉 host.docker.internal

从 Docker 18.03 版本开始,针对 Mac 和 Windows,你只需要在容器里把地址写成:

http://host.docker.internal:3000

Docker 守护进程会在内部动态运行一个 DNS 解析器。当容器查询 host.docker.internal 时,Docker 会将其智能解析为 你 Mac/Windows 电脑在局域网内的真实物理 IP 地址。这样,请求就能顺利绕出虚拟机,打到你的物理机上!


8. 💡 小小的最佳实践与架构建议

看完了原理,是时候拔高我们的架构视野了。在 2026 年的今天,硬编码 172.17.0.1 早就不是最佳实践了。作为有追求的开发者,小小推荐你采用以下姿势:

🥇 最佳实践一:全平台通杀的 --add-host 参数

如果你想让一套代码(一份配置)同时在 Linux 服务器和 Mac/Win 开发机上完美运行,你应该使用 --add-host 注入机制。

自 Docker 20.10+ 起,Linux 版本的 Docker 也开始原生支持 host.docker.internal 了,但需要我们在启动时显式声明:

docker run -d \
  --name my_app \
  --add-host=host.docker.internal:host-gateway \
  my_image
  • 魔法解析: host-gateway 是 Docker 内部的一个特殊占位符。在 Linux 下,它会被自动替换为 docker0 的网关 IP(即 172.17.0.1);在 Mac/Win 下,它由 Docker Desktop 自动处理。
  • 收益: 无论什么环境,你的代码只需要认准 host.docker.internal 这个域名即可,告别因为平台不同而修改配置文件的痛苦!

🥈 最佳实践二:慎用默认的 bridge(桥接)模式,使用自定义网络

在真实的生产环境中,极少有企业会把业务容器全扔进默认的 docker0 (172.17.0.1) 里。

  • 痛点: 默认 bridge 不支持通过容器名互访(内置 DNS 机制残缺)。
  • 推荐: 使用 docker network create my_net 创建自定义网络。在自定义网络中,不仅网段可以自由规划(避免与公司办公网段冲突),容器之间还可以直接通过名字(如 http://mysql_db:3306)互相解析,优雅至极。

🥉 最佳实践三:极端性能下的 host 网络模式

如果你的容器和宿主机之间的网络交互存在海量的高吞吐量(比如千万级 QPS 的 Redis),每次穿越 veth pairiptables 的 NAT 转发会带来微秒级的延迟损耗。
在 Linux 环境下,你可以使用 --network host

  • 原理: 打破结界!容器不再创建单独的 Network Namespace,而是直接和宿主机共享同一个网络栈。
  • 结果: 容器直接使用宿主机的真实 IP,性能达到 100% 物理机原生级别。但代价是隔离性变差,端口可能发生冲突。

9. 🙋 高频 Q&A (疑难杂症专诊)

在实际排查中,你可能还会遇到各种千奇百怪的问题。小小专门整理了几个高频的疑难杂症,对症下药:

Q1:为什么我 Linux 服务器上的 docker0 网关不是 172.17.0.1,而是 172.18.0.1 或者其他的?

小小学姐: 这是因为你的服务器之前可能经历过网络冲突。如果你的物理机所在局域网本身就在使用 172.17.x.x 网段,Docker 启动时很聪明地发现了冲突,就会自动顺延,使用 172.18.x.x 或其他内网保留网段。要以 ip addr show docker0 输出的实际 IP 为准。如果你想写死配置,可以通过修改 /etc/docker/daemon.json 中的 "bip" 属性强制指定 docker0 的网段。

Q2:我的服务绑定了 0.0.0.0,容器 ping 宿主机 172.17.0.1 也能通,但访问端口就是不通(Timeout),怎么回事?

小小学姐: 敲黑板!如果是 Timeout(超时)而不是 Connection refused(拒绝),99% 的概率是宿主机的防火墙(Firewalld / UFW / iptables 规则)把来自 docker0 网卡的请求包给拦截丢弃了!
尝试在宿主机执行命令开放端口:

  • CentOS: firewall-cmd --zone=public --add-port=3000/tcp --permanent && firewall-cmd --reload
  • Ubuntu: ufw allow from 172.17.0.0/16 to any port 3000
    让防火墙信任来自 Docker 网段的流量即可解决。

Q3:我能在宿主机上直接用 172.17.0.2 (容器的 IP) 来访问容器吗?

小小学姐: 在原生的 Linux 系统上,完全可以! 因为宿主机本身的内核拥有到 172.17.0.0/16 路由表条目,且宿主机和容器共享底层的 veth,它是互通的。
但在 Mac 和 Windows (Docker Desktop) 上,绝对不行! 因为前面说过,容器和那个 172.17.x.x 的网段是在隐藏的虚拟机里面的,对你的 Mac 物理机是不可见的。要访问容器,必须通过 -p 端口映射暴露给宿主机。


10. 🎓 总结

呼~跟着小小一口气走了这么远,不知你是否有一种“拨开云雾见青天”的通透感?

让我们最后再回顾一下这段知识旅程的精髓:
当你在讨论 172.17.0.1 时,你实际上在讨论的是:

  1. Linux 的 Network Namespace 创造了隔离的平行宇宙。
  2. Linux Bridge (docker0)veth pair 搭建了跨宇宙的桥梁。
  3. 172.17.0.1 既是 docker0 网桥在宿主机上的 真实 IP,也是容器通往外部世界的 默认网关
  4. 因为这是宿主机的 IP,所以容器向网关发包,本质就是发给宿主机。
  5. 成功的关键不仅在于网络通畅,更在于宿主机服务必须绑定 0.0.0.0,且防火墙不拦截。
  6. 不要忘了,平台是有差异的,跨平台最优雅的解法是利用 host.docker.internal

真正的技术大牛,从来不是记住某一段魔法代码或者神秘 IP,而是能站在系统的制高点,俯瞰数据包穿梭于虚拟与现实之间的每一个节点,洞察每一次连接的生死。

希望这篇超级详尽的教程,不仅让你搞懂了 172.17.0.1,更能让你对 Docker 和网络底层有一层全新的感悟。如果你的团队里还有小伙伴对 Docker 网络一知半解,或者还在饱受跨平台网络不通的折磨,快把这篇文章转给他们看看吧!

我是小小,那个热衷于把硬核原理揉碎了讲给你听的技术布道师。我们下期再见啦!💖🚀