3

从Docker容器中访问宿主机网络

 2 years ago
source link: https://nyan.im/p/access-host-from-docker
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在使用Docker部署应用时,Docker推荐的方式是将应用及其所依赖的服务(MySQL,Redis等)均使用Docker部署,并通过link或自定义网络相连接。但是,当应用所依赖的服务被安装在宿主机上时,我们需要让容器中的应用能够访问到部署在宿主机上的服务。本文将介绍实现这一目的的几种方案,并分析其优缺点。

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

Docker网络

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

Bridge

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK