一、none/host/bridge网络
Docker安装时会自动在host上创建3个网络,使用 docker network ls 查看:
none网络:就是什么都没有的网络,挂在这个网络下的容器ifconfig只能查到lo,没其他任何网卡,可通过 --network=none指定使用none网络。应用场景:一些安全性高并且不需要联网的应用可以使用none网络。(比如容器的唯一用途用于生成随机密码,这可以避免密码被窃取)
ho st网络:这个容器将不会获得一个独立的network namespace,而是和主机共同使用一个。连接到host网络的容器共享Docker host的网络,容 器的网络配置与host完全一样 。 可通过--network=host指定使用host网络 。应用场景:性能好, 若容器对网络传输效率有较高要求,可选择host网络,但要考虑端口冲突,Docker host(宿主机)上已使用的端口就不能用了。![]()
容器中看到的网卡和主机名跟宿主机host的完全一样。bridge网络:Docker 安装时会创建一个命名为 docker0 的 linux bridge, 创建容器时,若不指定--network,会默认挂到docker0上。它是Docker的默认网络模式,可以连接到主机的其它接口以及容器之间。
一个新的网络接口veth84f3dc9被挂在docker0,veth84f3dc9是新创建容器的虚拟网卡。
二、自定义网络
Docker提供了
3种user-defined网络驱动:
bridge、overlay、macvlan,
overlay与macvlan用于创建跨主机的网络。
通过bridge驱动创建bridge网络:
docker network create
--driver
bridge my_net
查看Docker host的网络结构变化
brctl show
查看my_net的配置信息
docker network inspect my_net

若要
指定IP段,只需在创建网段时指定
--subnet和--gateway参数:
docker network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 my_net2

创建容器,默认网络docker0,想使用新网络,
在创建容器时通过--network指定,--ip用于指定一个静态IP:
只有使用--subnet创建的网络才能指定静态IP.
docker run -it
--network=my_net2 --ip 172.22.16.8
busybox


三、容器间的多种通信方式
ip、Docker DNS SErver、joined容器、容器连接
3.1、容器间通信-IP通信
同一网络中的容器、网关间是可以通信的,my_net2与默认bridge(docker0)属于不同的网桥,二者间不连通。两个容器要能通信,必须有属于同一个网络的网卡 。方法:
创建容器时指定通过--network指定相同的网络; 对于已经创建的容器,为容器添加网卡 : docker network connect my_net2 httpd容器ID![]()
3.2、容器间通信-Docker DNS Server
IP通信不够灵活,因为部署应用前可能无法确定IP,可通过docker自带的DNS服务解决。1.10版本后,Docker daemon有个内嵌的 DNS Server,使容器可以通过“容器名”通信,只需要在启动时用--name为容器命名即可。docker run -it --network=my_net2 --name=bbox2 busybox
局限: 只能在自定义网络中使用dockers dns server
3.3、容器间通信-joined容器
joined容器时实现容器间通信的方式,它可以使多个容器共享一个网络栈, 共享网卡、配置信息,joined容器间可以通过127.0.0.1直接通信。先创建httpd容器: docker run -it --name=web1 httpd,然后创建busybox容器,并通过 - -network=container:web1指定joined容器为web1docker run -it --network=container:web1 busyboxbusybox容器与httpd容器的网卡mac地址、IP完全一样,他们共享了相同的网络栈,busybox可直接使用127.0.0.1访问web1的httpd服务。使用场景:
不同容器的程序希望通过loopback高效快速通信; 希望监控其它容器的网络流量。
3.4、容器连接
容器启动后,一般通过端口映射来使用容器提供的服务,端口映射只是使用容器服务的一种方式,还可以使用容器连接的方式使用容器服务。例子:两个容器,一个nginx,一个ubuntu,,启动nginx容器但不分配端口映射,再启动ubuntu,通过容器连接直接在ubuntu中访问nginx服务。1、启动nginx容器,不分配端口:docker run -d --name=nginx1 nginx # 宿主机无法访问2、启动ubuntu容器,并和nginx容器建立连接:docker run -itd --name=ubuntu --link nginx1:mylink ubuntu bash # nginx1是要建立连接的容器,mylink是连接的别名3、进入ubuntu容器:docker exec -it ubuntu bash在ubuntu控制台直接输入 env, 查看环境变量信息:
可以看到,docker为nginx创建了一系列环境变量,每个前缀变量是MYLINK(设置的别名)。开发者使用这些环境变量配置应用程序连接到nginx。该连接是安全的、私有的。
四、容器与外网访问
4.1、容器默认就能访问外网
能访问外网的本质是 NAT,查看docker host上的iptables规则 iptables -t -nat -S:
这条规则的含义:如果网桥 docker0 收到来自 172.17.0.0/16 网段的外出包,把它交给 MASQUERADE 处理。而 MASQUERADE 的处理方式是将包的源地址替换成 host 的地址发送出去,即做了一次网络地址转换(NAT)。![]()
4.2、外部访问容器--端口映射
docker可将容器对外提供服务的端口映射到host的某个端口,外网则可以通过该端口访问容器。容器启动时通过-p参数映射端口: docker run -d -p 80 httpd 或者 docker run -d -p 32768:80 httpd ( 将容器80端口映射到host上指定端口32768 )[root@syslog ~]# docker port 866acde6b80a # 通过docker ps或docker port查看到host映射的端口,容器80端口映射到host上的32768,可通过<host ip>:<port>访问容器的web服务了 80/tcp -> 0.0.0.0:32768 [root@syslog ~]# curl 10.21.144.111:32768 <html><body><h1>It works!</h1></body></html> [root@syslog ~]#
每映射一个端口,host会启动一个docker-proxy进程处理访问容器的流量。
外网访问容器用到了docker-proxy和iptables DNAT。
宿主机访问本机容器使用的是iptables DNAT。
外部主机访问容器或容器之间的访问是docker-proxy实现。
五、docker网络架构
早在Docker1.7版本中,网络部分代码就已经被抽离并单独成为了Docker的网络库,即libnetwork。在此之后,容器的网络模式也被抽像变成了统一接口的驱动。为了标准化网络的驱动开发步骤和支持多种网络驱动,Docker公司在libnetwork中使用了CNM(Container Network Model)。CNM定义了构建容器虚拟化网络的模型。同时还提供了可以用于开发多种网络驱动的标准化接口和组件。libnetwork和Docker daemon及各个网络驱动的关系可以通过下面的图进行形象的表示。
如上图所示,Docker daemon通过调用libnetwork对外提供的API完成网络的创建和管理等功能。libnetwrok中则使用了CNM来完成网络功能的提供。而CNM中主要有沙盒(sandbox)、端点(endpoint)、网络(network)这3种组件。libnetwork中内置的5种驱动( bridge驱动、host驱动、overlay驱动、remote驱动、null驱动)则为libnetwork提供了不同类型的网络服务。
docker的bridge自定义网络之间默认是有域名解析的-----容器间通信-Docker DNS Server;docker的bridge自定义网络与系统自带的网桥之间默认是有解析的;但是docker的系统自带的网桥之间默认是没有解析的。docker的bridge自定义网络之间:双方可以随便添加对方的网卡docker的bridge自定义网络与系统自带的网桥之间:只能是系统自带的网桥对应的容器 添加 bridge自定义网络对应的容器的网卡,而反过来会报错。但是docker的系统自带的网桥之间:是可以通信的,因为是在一个网络桥接上。docker 1.10开始,内嵌了一个DNS server。dns解析功能必须在自定义网络中使用。