001-docker-net-网络设置分类、Bridge详解、mac docker说明

时间:2024-03-07 07:22:10

一、概述

参看文章: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 不同。