001-docker-net-网络设置分类、Bridge详解、mac docker说明
一、概述
参看文章:https://docs.docker.com/engine/reference/commandline/network_create/
Docker自身的4种网络工作方式,和一些自定义网络模式
安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络)、 none 、host
host:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
Container:创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围。
None:该模式关闭了容器的网络功能。
Bridge:此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。
以上都是不用动手的,真正需要配置的是自定义网络。
二、网络介绍
2.1、网络设置
当你安装Docker时,它会自动创建三个网络。你可以使用以下docker network ls命令列出这些网络:
$ docker network ls NETWORK ID NAME DRIVER 7fca4eb8c647 bridge bridge 9f904ee27bf5 none null cf03ee007fb4 host host
Docker内置这三个网络,运行容器时,你可以使用该--network标志来指定容器应连接到哪些网络。
该bridge网络代表docker0所有Docker安装中存在的网络。除非你使用该docker run --network=<NETWORK>选项指定,否则Docker守护程序默认将容器连接到此网络。
我们在使用docker run创建Docker容器时,可以用 --net 选项指定容器的网络模式,Docker可以有以下4种网络模式:【bridge host ipvlan macvlan null overlay】
host模式:使用 --net=host 指定。
none模式:使用 --net=none 指定。
bridge模式:使用 --net=bridge 指定,默认设置。
container模式:使用 --net=container:NAME_or_ID 指定。
2.2、host网络
与宿主机在同一个网络中,但没有独立IP地址。众所周知,Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其他的Network Namespace隔离。一个Docker容器一般会分配一个独立的Network Namespace。但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
例如,我们在10.10.0.186/24的机器上用host模式启动一个含有nginx应用的Docker容器,监听tcp80端口。
# 运行容器; $ docker run --name=nginx_host --net=host -p 80:80 -d nginx 74c911272942841875f4faf2aca02e3814035c900840d11e3f141fbaa884ae5c # 查看容器; $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 74c911272942 nginx "nginx -g 'daemon ..." 25 seconds ago Up 25 seconds nginx_host
当我们在容器中执行任何类似ifconfig命令查看网络环境时,看到的都是宿主机上的信息。而外界访问容器中的应用,则直接使用10.10.0.186:80即可,不用任何NAT转换,就如直接跑在宿主机中一样。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
$ netstat -nplt | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 27340/nginx: master
小结:
直接使用宿主机的 IP 地址,最简单,但是容器跟宿主机共享,直接对外暴露,安全性低。
Docker 17.06+ 支持。
仅支持 Linux。
2.3、Container
在理解了host模式后,这个模式也就好理解了。这个模式指定新创建的容器和已经存在的一个容器共享一个Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。
2.4、None
该模式将容器放置在它自己的网络栈中,但是并不进行任何配置。实际上,该模式关闭了容器的网络功能,在以下两种情况下是有用的:容器并不需要网络(例如只需要写磁盘卷的批处理任务)。禁用网络配置,通常是在使用第三方网络配置插件时设置。
2.5、overlay
在docker1.7代码进行了重构,单独把网络部分独立出来编写,所以在docker1.8新加入的一个overlay网络模式。Docker对于网络访问的控制也是在逐渐完善的。
docker 自带的跨主机网络模型
2.6、Bridge
相当于Vmware中的Nat模式,容器使用独立network Namespace,并连接到docker0虚拟网卡(默认模式)。通过docker0网桥以及Iptables nat表配置与宿主机通信;
bridge模式是Docker默认的网络设置,
当docker服务启动后,会创建一个名字叫docker0的虚拟网桥,然后选一个与宿主机不一样的网络ip地址以及子网分配给docker0
另外每创建一个容器就会新增一个容器网卡,此模式会为每一个容器分配Network Namespace、设置IP等,然后以桥接方式架到docker0网桥中,docker0会以NAT地址转换的方式通过宿主机的网卡,从而与公网进行通信。
2.6.1、修改Docker0网桥默认网段
它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络。
Docker 默认指定了 docker0 接口 的 IP 地址和子网掩码,让主机和容器之间可以通过网桥相互通信,它还给出了 MTU(接口允许接收的最大传输单元),通常是 1500 Bytes,或宿主主机网络路由上支持的默认值。这些值都可以在服务启动的时候进行配置。
1、默认 docker0 网桥信息
ifconfig docker0 docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:db:0d:17:0c txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
2、修改文件 /etc/docker/daemon.json 添加内容 "bip": "ip/netmask" [切勿与宿主机同网段]
vim /etc/docker/daemon.json { "bip":"192.168.100.1/24" }
3、重启服务并查看
systemctl restart docker
或者:service docker restart 执行步骤一查看网卡信息
2.7、macvlan
macvlan 网卡虚拟化技术,可以在一张物理网卡上配置多个 MAC 地址,对应多个 interfaces,每个 interface 一个ip。优点是性能极好,不需要创建Linux bridge,而是直接通过interface连接到物理网络。
Docker 中,可以为每个容器分配一个 MAC 地址,直接通过 MAC 地址转发数据。
需要考虑网络性能时,或者希望应用直接通过 物理网卡连接到网络时可以使用。
2.8、多docker通讯
参看:https://www.cnblogs.com/jayhou/p/12319655.html
三、Bridge详解
Docker 默认设置的网络模式
3.1、Linux和mac网络实现
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 就创建了在主机和所有容器之间一个虚拟共享网络。
ifconfig | grep docker -A 8
ifconfig | grep eth0 -A 7
mac系统:
因为实现的方式不同(见下),所以没有 docker0 网卡。
3.1.1、Linux 和 Mac 网络的区别
1、Linux 下的网络结构【下图1】
Docker 在 Linux 的自带内核上实现的,所以 Docker 在 Linux 上安装后, 会创建一个 docker0 的虚拟网卡,Linux 宿主机和 Docker 中的容器通过该网卡进行通信。
2、Mac 下的网络结构: 【上图2】
Docker 在 Mac 中的实现是通过 Hypervisor 创建一个轻量级的虚拟机,然后 将 docker 放入到虚拟机中实现。Mac OS 宿主机和 Docker 中的容器通过 /var/run/docker.sock 这种 socket 文件来通信,所以在 Mac OS 中 ping 容器的 IP,在容器中 ping 宿主机的 IP 就不通。
四、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 创建虚拟机的方式来创建容器。
4.1、Docker Desktop for Mac
4.1.1、宿主机和容器的端口映射
docker run -p HOST_PORT:CLIENT_PORT xxxxx
e.g : doker run -p 80:80 -d nginx
4.1.2、Mac OS 中的限制
没有 docker0 bridge 网卡。
宿主机不能 ping 通容器的ip,宿主机
不能从主机 Mac 访问 Linux bridge.
4.1.3、mac 宿主机 和 容器互通 的解决方案
1、容器内访问宿主机,在 Docker 18.03 过后推荐使用 特殊的 DNS 记录 host.docker.internal 访问宿主机。但是注意,这个只是在 Docker Desktop for Mac 中作为开发时有效。 网关的 DNS 记录: gateway.docker.internal。原文 Docker for Mac
2、宿主机访问容器,使用本机 localhost 端口映射功能,使用 –publish(单个端口), -p(单个端口), -P(所有端口) 将本机的端口和容器的端口映射。
3、宿主机访问容器,使用 -p 参数映射端口。容器访问宿主机,可以在宿主机使用下面的命令获取 宿主机的 ip 地址:
ps -ef | grep -i docker | grep -i "\-\-host\-ip" |awk -F "host-ip" '{print $2}' | awk -F '--lowest-ip' '{print $1}'
在宿主机的 mac 上查看 docker deamon的进程,可以找到启动的配置参数如下
ps -ef |grep -i docker
--host-ip
从进程中可以提取到宿主机的 ip 地址,这个 ip 地址的网段在 Docker for Mac –> Preferences – > Advanced –> Docker subnet 中配置。
旧版本 使用比较麻烦,新版本直接配置,网路可通
可以在容器中安装 Rinetd 来转发本地的 socket 请求到宿主机。
4.2、Docker Toolbox
目的是为了适配老版本的 Mac OS 和 Windows,实现方式和 Docker Desktop for Mac 不同。