容器link互联的原理和问题
新创建的容器默认会被分配一个172.17.0.1 B类地址,容器之间也就是单独的内网,他们跟宿主机通讯就需要借助虚拟的网桥docker0,docker服务重启后,容器IP会自动重新获取,也就是容器的IP是不固定的
宿主机上查看容器docker0网卡信息
查看容器IP
那么问题来了,由于IP地址是随机分配的,那么容器之间访问就不能通过IP地址访问,那么docker就提供了一个link参数的方式,原理就是通过本地host的方式访问和生成环境变量
关于操作和使用网上有很多资料,这边主要说下,这种方式的不好的地方
- 需要维护大量的host表
- 需要借助dns解析
- 不方便容器之间隔离
官方也已经很早就提出不建议使用link方式容器互联,最终命令可能会被删除,目前最新版19.03.5版本还能使用,淘汰的技术也就没有必要研究了
参考:https://docs.docker.com/network/links/
容器network互联
架构和原理可以查看官网资料:点击访问
官方提供的五种网络驱动:
- bridge桥接,默认的网络驱动程序。这个概念会跟虚拟机桥接模式弄混,这里的桥接就是创建单独的内网,也就是虚拟机的NAT模式,然而其与外界通信使用NAT模式,增加了通信的安全性。
- host主机,Docker容器中的进程处于宿主机的网络环境中,相当于Docker容器和宿主机共同用一个network namespace,使用宿主机的网卡、IP和端口等信息,这个才是虚拟机说的桥接模式。
- null驱动,容器只有一个loopback网卡驱动,docker不会为容器添加网卡、配置IP等信息,通常与自定义网络驱动程序一起使用,它给了用户最大的自由度来自定义容器的网络环境。
- overlay,这个概念说的就是大二层的,利用Vxlan技术促进群集服务和独立容器之间或不同Docker守护程序上的两个独立容器之间的通信,消除了网络层的需要。
- macvlan,macvlan 本身是 linux kernel 模块,其功能是允许在同一个宿主机物理网卡上配置多个 MAC 地址,即多个 interface,每个 interface 可以配置自己的 IP。
使用场景
-
当您需要多个容器在同一Docker主机上进行通信时,最好使用用户定义的网桥网络。
-
当容器与宿主机网络不隔离的时候,但又希望容器的其他方面隔离时(系统层),主机网络是最佳选择。
-
当您需要在不同Docker主机上运行的容器进行通信时,或者当多个应用程序使用集群服务一起工作时,覆盖网络是最好的。
-
从VM设置迁移或需要容器看起来像网络上的物理主机(每个主机都有唯一的MAC地址)时,Macvlan网络是最好的。
-
都不满足的话可以使用,第三方网络插件使您可以将Docker与专用网络堆栈集成。
查看本地docker的网络驱动,docker默认创建了3种模式
默认启动容器没有指定就是桥接模式通过link方式建立容器互联,我这边配置2个容器看下默认桥接的信息
bridge网络创建了一个Subnet和Gateway,在Containers列表中两个容器分别分配到了172.17.0.2和172.17.0.3两个IP也就是我的2个服务容器自动获取到的IP地址。
用户定义的网桥和默认网桥之间的区别
- 用户定义的桥可在容器化应用程序之间提供更好的隔离和互操作性。
- 用户定义的网桥可在容器之间提供自动DNS解析。
- 容器可以随时随地从用户定义的网络连接和分离。
- 每个用户定义的网络都会创建一个可配置的网桥,默认的不给配置IP,网关等等。
- 默认网桥网络上的链接容器共享环境变量。
总结:建议自己创建一个网桥,配置相关信息,不适用默认网桥
自定义桥接网络配置
创建
用法:docker network create [OPTIONS] NETWORK
Options:
--attachable Enable manual container attachment
--aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
--config-from string The network from which copying the configuration
--config-only Create a configuration only network
-d, --driver string Driver to manage the Network (default "bridge")
--gateway strings IPv4 or IPv6 Gateway for the master subnet
--ingress Create swarm routing-mesh network
--internal Restrict external access to the network
--ip-range strings Allocate container ip from a sub-range
--ipam-driver string IP Address Management Driver (default "default")
--ipam-opt map Set IPAM driver specific options (default map[])
--ipv6 Enable IPv6 networking
--label list Set metadata on a network
-o, --opt map Set driver specific options (default map[])
--scope string Control the network's scope
--subnet strings Subnet in CIDR format that represents a network segment
docker network create \
--driver=bridge \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
zabbix
创建一个名为zabbix的桥接网络(driver未指定默认就是桥接)
子网为192.168.1.0/24,网关为192.168.1.1
--ip-range还可以指定IP范围
查看新建的网桥信息
docker network inspect zabbix
启动新容器指定network
docker run -itd --network zabbix --ip 192.168.1.120 centos
指定网桥和IP地址,不指定ip就是自动获取
查看容器的IP地址
docker exec -it cfdc9f9b182a ip addr
测试把docker服务重启后容器的IP是否会发送改变
IP地址还是我设置的,如果是默认桥接模式,自动重新后IP会随机获取,好处就是上面说到的,我这边正好搭建了一个zabbix,官网方案是link来互联容器但我改成network,不是基于host来访问,服务器就直接填写IP地址。
docker network通过别名来访问
–network-alias 指定别名
docker run -itd --network zabbix --ip 192.168.1.121 --network-alias centos7 centos
network别名和link别名起到一个作用,但是实现过程不是通过hosts,而是使用docker嵌入式DNS服务器,配置别名后所有的虚拟机都可以通centos7别名访问到这个容器,link需要针对所有的容器配置。
参考docker嵌入式DNS:点击访问