1. Docker 网络插件(Docker’s networking subsystem is pluggable)
1.1. bridge
- Docker 默认设置的网络模式。
- Linux :
- Docker 宿主机创建一个 docker0网卡, 随机分配一个本地未占用的私有网段,e.g: 172.17.0.1/16;
- Docker 容器会增加一个 eth0 的网卡,随机分配同一网段: e.g 172.17.0.0/16 中的一个 ip.
- 当 Docker 创建一个容器时,同时会创建了一对 veth pair 接口(当数据包发送到一个接口时,另外一个接口也可以收到相同的数据包)。这对接口一端在容器内,即 eth0;另一端在本地并被挂载到 docker0 网桥,名称以 veth 开头(例如 vethAQI2QT)。通过这种方式,主机可以跟容器通信,容器之间也可以相互通信。Docker 就创建了在主机和所有容器之间一个虚拟共享网络。
1 | [root@test: ~]# ifconfig | grep docker -A 8 |
- Mac :
因为实现的方式不同(见下),所以没有 docker0 网卡。
1.1.1. Linux 和 Mac 网络的区别
- Linux 下的网络结构:
Docker 在 Linux 的自带内核上实现的,所以 Docker 在 Linux 上安装后, 会创建一个 docker0 的虚拟网卡,Linux 宿主机和 Docker 中的容器通过该网卡进行通信。
- Mac 下的网络结构:
Docker 在 Mac 中的实现是通过 Hypervisor 创建一个轻量级的虚拟机,然后 将 docker 放入到虚拟机中实现。Mac OS 宿主机和 Docker 中的容器通过 /var/run/docker.sock 这种 socket 文件来通信,所以在 Mac OS 中 ping 容器的 IP,在容器中 ping 宿主机的 IP 就不通。
1.2. host :
- 直接使用宿主机的 IP 地址,最简单,但是容器跟宿主机共享,直接对外暴露,安全性低。
- Docker 17.06+ 支持。
- 仅支持 Linux。
1.3. overlay :
- docker 自带的跨主机网络模型
1.4. macvlan :
- macvlan 网卡虚拟化技术,可以在一张物理网卡上配置多个 MAC 地址,对应多个 interfaces,每个 interface 一个ip。优点是性能极好,不需要创建Linux bridge,而是直接通过interface连接到物理网络。
- Docker 中,可以为每个容器分配一个 MAC 地址,直接通过 MAC 地址转发数据。
- 需要考虑网络性能时,或者希望应用直接通过 物理网卡连接到网络时可以使用。
1.5. none :
- 禁用网络配置,通常是在使用第三方网络配置插件时设置。
1.6. Network plugins : 插件
- 从 Docker Hub hove 第三方获取
2. Docker 在 Mac 中的两种实现方式
- docker 在 Mac 中有两种实现,一种是基于 HyperKit (Docker Desktop for Mac),另一种是基于Virtual Box(Docker Toolbox).
- 两者的区别会导致宿主机和容器直接网络访问方式不同,Docker Desktop for Mac 是基于 /var/run/docker.sock 文件。Docker Toolbox 是基于虚拟网卡。还有就是管理容器的方式不一样, Docker Desktop for Mac 是使用 HyperKit, 基于 Hypervisor 的轻量级虚拟化机;Docker Toolbox 则是使用 Virtual Box 创建虚拟机的方式来创建容器。
2.1. Docker Desktop for Mac
2.1.1. 1. 宿主机和容器的端口映射
docker run -p HOST_PORT:CLIENT_PORT xxxxx
e.g : doker run -p 80:80 -d nginx
2.1.2. 2. Mac OS 中的限制
- 没有 docker0 bridge 网卡。
- 宿主机不能 ping 通容器的ip,宿主机
- 不能从主机 Mac 访问 Linux bridge.
2.1.3. 3. mac 宿主机 和 容器互通 的解决方案
容器内访问宿主机,在 Docker 18.03 过后推荐使用 特殊的 DNS 记录 host.docker.internal 访问宿主机。但是注意,这个只是在 Docker Desktop for Mac 中作为开发时有效。 网关的 DNS 记录: gateway.docker.internal。
宿主机访问容器,使用本机 localhost 端口映射功能,使用 –publish(单个端口), -p(单个端口), -P(所有端口) 将本机的端口和容器的端口映射。
宿主机访问容器,使用 -p 参数映射端口。容器访问宿主机,可以在宿主机使用下面的命令获取 宿主机的 ip 地址:
1
ps -ef | grep -i docker | grep -i "\-\-host\-ip" |awk -F "host-ip" '{print $2}' | awk -F '--lowest-ip' '{print $1}'
在宿主机的 mac 上查看 docker deamon的进程,可以找到启动的配置参数如下
从进程中可以提取到宿主机的 ip 地址,这个 ip 地址的网段在 Docker for Mac –> Preferences – > Advanced –> Docker subnet 中配置。
可以在容器中安装 Rinetd 来转发本地的 socket 请求到宿主机。
CentOS 安装
添加第三方 64 位源:
1
2
3
4
5
6
7
8echo "
[nux-misc]
name=Nux Misc
baseurl=http://li.nux.ro/download/nux/misc/el6/x86_64/
enabled=0
gpgcheck=1
gpgkey=http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
" > /etc/yum.repos.d/nux-misc.repo安装 : yum –enablerepo=nux-misc install rinetd
Ubuntu 安装
- apt-get install rinetd
编译安装
- 执行下面的命令:
cd ~ wget http://www.boutell.com/rinetd/http/rinetd.tar.gz tar zxvf rinetd.tar.gz cd rinetd mkdir -p /usr/man/man8 make && make install
- 执行下面的命令:
配置 : vi /etc/rinetd.conf
### [bindaddress] [bindport] [connectaddress] [connectport] ### 绑定的地址 绑定的端口 连接的地址 连接的端口 ### [Source Address] [Source Port] [Destination Address] [Destination Port] ### 源地址 源端口 目的地址 目的端口 0.0.0.0 8080 172.19.94.3 8080 0.0.0.0 2222 192.168.0.103 3389 1.2.3.4 80 192.168.0.10 80 allow *.*.*.* logfile /var/log/rinetd.log
启动: rinetd start
关闭: rinetd stop
查看帮助: rinetd -h
如果以上方案都不OK,那就用 Docker Toolbox
2.2. Docker Toolbox
目的是为了适配老版本的 Mac OS 和 Windows,实现方式和 Docker Desktop for Mac 不同。