在使用Docker部署应用时,Docker推荐的方式是将应用及其所依赖的服务(MySQL,Redis等)均使用Docker部署,并通过linkæˆ–è‡ªå®šä¹‰ç½‘ç»œç›¸è¿žæŽ¥ã€‚ä½†æ˜¯ï¼Œå½“åº”ç”¨æ‰€ä¾èµ–çš„æœåŠ¡è¢«å®‰è£…åœ¨å®¿ä¸»æœºä¸Šæ—¶ï¼Œæˆ‘ä»¬éœ€è¦è®©å®¹å™¨ä¸­çš„åº”ç”¨èƒ½å¤Ÿè®¿é—®åˆ°éƒ¨ç½²åœ¨å®¿ä¸»æœºä¸Šçš„æœåŠ¡ã€‚æœ¬æ–‡å°†ä»‹ç»å®žçŽ°è¿™ä¸€ç›®çš„çš„å‡ ç§æ–¹æ¡ˆï¼Œå¹¶åˆ†æžå…¶ä¼˜ç¼ºç‚¹ã€‚

首先我们需要了解一些关于Docker网络的基础知识。

Docker网络 Docker提供了5种网络类型,这里介绍其中常见的两种:bridge及host

Bridge Bridge是Docker默认使用的网络类型。如图,网络中的所有容器可以通过IP互相访问。Bridge网络通过网络接口docker0 与主机桥接,可以在主机上通过ifconfig docker0查看到该网络接口的信息。

Host Host模式下,容器的网络接口不与宿主机网络隔离。在容器中监听相应端口的应用能够直接被从宿主机访问。host网络仅支持Linux。

方案 方案1:使用host模式 通过docker run å¯åŠ¨å®¹å™¨æ—¶åŠ å…¥--net=host 参数,或在compose文件中指定network_mode: "host" ,例如:

version: '3' services: foo: container_name: "foo" image: "foo/bar" ports: - "8000:8000" network_mode: "host" restart: always

该参数指定该容器使用hostç½‘ç»œæ¨¡å¼ï¼Œå› æ­¤ä¹Ÿæ— éœ€æ˜ å°„ç«¯å£ã€‚

优点

  • 最简单粗暴的解决方案,方便快捷。

缺点

  • host网络没有与宿主机网络隔离,可能引发安全隐患或端口冲突。
  • 仅适用于Linux。

方案2:使用docker0网络的默认网关地址 在默认的bridge模式下,docker0网络的默认网关即是宿主机。在Linux下,docker0网络通常会分配一个172.17.0.0/16的网段,其网关通常为172.17.0.1;macOS下的网段则为192.168.65.0/24,网关为192.168.65.1。在容器中使用该IP地址即可访问宿主机上的各种服务。

需要注意的是,这种情况下,经由docker0ç½‘æ¡¥è€Œæ¥çš„æµé‡ä¸ç»è¿‡å®¿ä¸»æœºçš„æœ¬åœ°å›žçŽ¯ï¼Œå› æ­¤éœ€è¦å°†å®¿ä¸»æœºä¸Šçš„åº”ç”¨ï¼ˆMySQL,Redis等)配置为监听0.0.0.0。

优点

  • 避免了方案1的缺点

缺点

  • æ­¤IPå¹¶ä¸ä¸€å®šå®Œå…¨å›ºå®šï¼Œå¯èƒ½ä¼šå› ç³»ç»ŸåŠé…ç½®è€Œå‘ç”Ÿå˜åŒ–ã€‚
  • 容器经由docker0ç½‘æ¡¥æ— æ³•è®¿é—®åˆ°ç›‘å¬åœ°å€æ˜¯127.0.0.1的应用。需要将MySQL等配置为监听0.0.0.0。

方案3:Docker提供的指向宿主机的DNS macOS版Docker提供了一个指向宿主机的域名docker.for.mac.host.internal ã€‚åœ¨éœ€è¦è®¿é—®å®¿ä¸»æœºæœåŠ¡æ—¶ä½¿ç”¨æ­¤åŸŸåå³å¯ã€‚å…¶å®žçŽ°åŽŸç†æœ‰äººè¿›è¡Œäº†å¦‚ä¸‹ç ”ç©¶ï¼š

Understanding the ‘docker.for.mac.localhost’ behavior – Docker Desktop for Mac – Docker Forums

优点

  • 该DNS是动态的,能够适用于不同的网络环境及配置。

缺点

  • 容器经由docker0ç½‘æ¡¥æ— æ³•è®¿é—®åˆ°ç›‘å¬åœ°å€æ˜¯127.0.0.1的应用。需要将MySQL等配置为监听0.0.0.0。
  • 仅适用于macOS。实际上,已经有人在GitHub上提出Issue,请求在Linuxä¸Šæ·»åŠ ç±»ä¼¼çš„ç‰¹æ€§ã€‚

方案4:在容器中获取宿主机地址 在Dockerfile的CMDéƒ¨åˆ†æ·»åŠ å¦‚ä¸‹ä¸€æ¡å‘½ä»¤ï¼š

ip -4 route list match 0/0 | awk ‘{print $3 “host.docker.internal”}’ >> /etc/hosts

ip -4 route list match 0/0 命令会列出当前系统的默认网关,并将host.docker.internal 域名解析至它。

请注意ip命令并不一定随镜像附带,如果没有的话,使用apt install iproute2 安装。

优点

  • 综合了方案2和3的优点

缺点

  • 容器经由docker0ç½‘æ¡¥æ— æ³•è®¿é—®åˆ°ç›‘å¬åœ°å€æ˜¯127.0.0.1的应用。需要将MySQL等配置为监听0.0.0.0。

参考资料 配置 docker0 网桥 · Docker —— 从入门到实践

networking – What is the relation between docker0 and eth0? – Stack Overflow

Docker的桥接网络是怎么工作的 | 懒程序员改变世界

Docker – add host.docker.internal on linux

docker 跨主机网络:overlay 简介 | Cizixs Write Here