简介

自从用上 OrbStack 以后,就回不去了,OrbStack 会为容器注册域名到本机的 mDNS 中,这为新手解决了几个难以理解的问题:

  • 同一个项目在宿主机和容器中访问数据库容器的 HOST 不同
  • 数据库容器的端口需要映射到宿主机端口

例如我问本地开发环境启动了 mysql 和 redis 容器,并为它们分配了如下域名:

  • mysql.database.local
  • redis.database.local

当 OrbStack 中对应的容器启动后,OrbStack 会自动向 macOS 的 mDNS 注册,从而实现可以通过域名访问容器。

OrbStack 网络架构

OrbStack 使用自定义的网络栈来管理容器和主机之间的通信,默认情况下:

  • 容器内部 IP(如 10.0.8.33):这是容器在 OrbStack 的虚拟网络(通常是一个桥接网络,例如 bridge101)中分配的私有 IP 地址,属于类似 10.0.0.0/8 的子网。这种 IP 通常只在 OrbStack 的内部网络中可见,用于容器间的通信或与虚拟机的交互。

  • 外部访问 IP(如 198.19.248.8):OrbStack 会为容器分配一个对外暴露的 IP 地址,通常在 198.19.248.0/23 范围内。这是 OrbStack 的网络代理层(运行在 macOS 主机上)提供的地址,用于将外部流量(例如通过 container-name.orb.local 的域名访问)路由到容器。

换句话说,10.0.8.33 是容器在内部网络中的实际地址,而 198.19.248.8 是 OrbStack 的网络层为该容器提供的外部代理地址。

容器启动后,可以通过如下命令来查看 mDNS 中的记录:

dns-sd -Q mysql.database.local
DATE: ---Tue 11 Mar 2025---
13:51:43.488  ...STARTING...
Timestamp     A/R  Flags         IF  Name                          Type   Class  Rdata
13:51:43.623  Add  2             26  mysql.database.local.         Addr   IN     198.19.248.8

起因

一切都看似美好,直到我们的项目中使用了 Swoole 这个 PHP 扩展,我在 Swoole 项目中无法使用前面提到的 mysql.database.local 来连接数据库容器。

会得到如下错误:

php bin/hyperf.php migrate --path migrations/tenant

In Connection.php line 1169:
                                                                                                    
  SQLSTATE[HY000] [2002] DNS Lookup resolve failed (SQL: select `enterprise_id` from `enterprise`)  
                                                                                                    

In Connector.php line 107:
                                                    
  SQLSTATE[HY000] [2002] DNS Lookup resolve failed                                      

最初也没在意这个问题,还以为是 OrbStack 的网络兼容性问题,直到后来另一位同事的 macOS 上更我我同样的配置它却可以在 Swoole 项目中访问 OrbStack 中定义的域名。

排查

于是我用排除法,对比了我和同事电脑的环境配置差异,对比下来发现就比他多启用了个 c-ares 库,从命名上完去看不出它跟 DNS 有啥关系,后来一查才知道,c-ares 是一个异步 DNS 解析库,它适用于需要在不阻塞的情况下执行 DNS 查询或需要并行执行多个 DNS 查询的应用程序。

Swoole 默认不开启,需要在编译 Swoole 时增加 –enable-cares 参数才能开启。

而这个库是不支持 mDNS 记录的查询的。

解决方案

  • 重新编译 Swoole 扩展,编译时不开启 cares
  • 为容器设置固定 IP,然后在 /etc/hosts 中手动添加解析记录

I hope this is helpful, Happy hacking…