docker网络(容器互联)
理解docker0
docker和ubuntu的通信
- ip addr 查看网络的配置
- 查看启动的容器的网络配置
docker exec -it tomcat01 ip addr
- 查看容器的内部网络地址,ip addr,发现容器启动的时候会得到一个96: eth0@if97的ip地址,docker自动分配的
-
-
思考:linux 能不能ping 通我们的容器内部?
- 可以
-
原理
- 我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0,桥接模式,使用的技术就是evth-pair技术。
-
在启动一个容器,我们发现又多了一对网卡
-
我们发现这个容器带来的网卡,都是一对对的
- evth-pair 就是一对虚拟设备接口,他们都是成对出现的,一端连着协议,一端连着彼此
- 正是因为有这个特性,evth-pair充当一个桥梁,连接各种虚拟网络设备的
-
容器之间通信
-
我们来测试下两个容器之间是不是能ping通
- 终极原理:docker0的路由转发
- 我们感觉好像是容器之间的通信是直接联通的,其实并不是,而是我们的docker0充当了路由器的功能,首先tomcat01发送一条信息通过evth-pair技术传到docker0,然后docker0通过路由配置/广播机制,将我们的信息在通过evth-pair技术传送到tomcat02中
- 所有的容器在不指定网络的情况下,都是docker0进行路由的,docker都会给我们的容器分配一个默认的可用的ip
- docker中所有的网络接口都是虚拟的,虚拟的转发效率高!
- 当我们删除了这个容器的时候,evth-pair也是直接就消失了,docker自动管理
通过名字来进行网络通信(不推荐)
-
通过名字来进行网络通信
-
问题
- 我们每次重新启动容器,docker都是重新自动的分配evth-pair的地址,这样就会产生一个问题,假设我们写了一个服务,我们在服务中访问mysql,我们的MySQL是通过容器开启的,项目代码中写的是mysql的容器地址,mysql突然崩了,在重启ip就发生了变化,我们服务访问不到mysql,这样服务就会出现问题
-
解决办法
-
通过容器名称进行访问,访问到的是容器的ip地址,容器的名称不会变,ip即使变了,我们指向名字依旧可以找到ip
-
技术 --link
-
docker run -d -P --name tomcat03 --link tomcat02 tomcat -
-
-
反过来使用tomcat02去ping 容器tomcat03,是否能ping通?
- 不能
-
--link的单项连接(使用局限太大,不推荐)
- 原因
- 本质
- 实际上就是我们在hosts文件中增加了一个172.17.0.3 tomcat02 容器id
- 原因
-
-
查看网络详情
-
docker network inspect bridge-
结果
-
root@iZbp12kyfwxfku3288sr59Z:~# docker network inspect bridge [ { "Name": "bridge", "Id": "d80554cf321bff3d2821acfe37abdff08809fa1ee0f4a8d37693bb949e529476", "Created": "2020-10-02T13:30:57.993132975+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" # docker0 } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { # 容器的网络 "6fcc850bb9dda8098daae0129af2995a823330a79d6fc74a536e4f53b5bc093a": { "Name": "tomcat02", "EndpointID": "e54399c3dd68ca240379dfff6251652a888e61fa880b90334ac8cff872794521", "MacAddress": "02:42:ac:11:00:03", "IPv4Address": "172.17.0.3/16", # tomcat02的网络 "IPv6Address": "" }, "8d2b39b543083ba0028212ccf2fc986eeb9b7591662c28b0171321c7dcaf93d5": { "Name": "tomcat01", "EndpointID": "453f09d79583b22ce429d2054eb720b0666d2cfb0c5978379b6a7dd89aa2907f", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", # tomcat01的网络 "IPv6Address": "" }, "acf6df2a5d4e36e23b32aad793f1d28b9f91dfc1a53ecac569ec1c64f812ed3e": { "Name": "tomcat03", "EndpointID": "60eeb95e2e97d91070378771d2a4bd384e55e2285603232e067dd6cb25ebd622", "MacAddress": "02:42:ac:11:00:04", "IPv4Address": "172.17.0.4/16", # tomcat03的网络 "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ] -
查看所有网络
-
docker network ls -
结果
-
root@iZbp12kyfwxfku3288sr59Z:~# docker network ls NETWORK ID NAME DRIVER SCOPE d80554cf321b bridge bridge local 0985e4179804 host host local d95b28d99da4 none null local -
网络模式
- Bridge:桥接 docker(默认,自己创建也是使用的是桥接的模式)
- none:不配置网络
- Host: 和宿主机共享网络
- Container:容器网络联通(不推荐)
-
-
-
-
自定义网络(常见)
-
自定义网络
- 默认命令的完整版
docker run -d -P --name tomcat01 --net bridge tomcat-
我们直接使用的run命令
--net bridge而这个是我们的docker0 -
创建自定义网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet- 参数
- --driver bridge 网络模式
- --subnet 192.168.0.0/16 定义网段和主机数目 255*255
- --gateway 192.168.0.0 网关路由
-
自定义网络mynet的详细信息
-
root@iZbp12kyfwxfku3288sr59Z:~# docker network inspect mynet [ { "Name": "mynet", "Id": "11690a7560b3c847045e9216a2fb3e91d90b0c8c8c5c3711ac57ce834ed0991b", "Created": "2020-10-04T20:50:40.991733452+08:00", "Scope": "local", "Driver": "bridge", # 网络模式 "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "192.168.0.0/16", # 子网掩码 "Gateway": "192.168.0.1" # 网关 } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": {}, "Options": {}, "Labels": {} } ]
-
-
创建三个自定义网络下的容器
-
root@iZbp12kyfwxfku3288sr59Z:~# docker network inspect mynet [ { "Name": "mynet", "Id": "11690a7560b3c847045e9216a2fb3e91d90b0c8c8c5c3711ac57ce834ed0991b", "Created": "2020-10-04T20:50:40.991733452+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "192.168.0.0/16", "Gateway": "192.168.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { # 在这个部分的容器选项中,包含了三个容器 "5ef9b87d364aafd27a509422bb24cdfbd249c2bcf74b2297b47bbfae1601b1e8": { "Name": "tomcat-net-01", "EndpointID": "e83f9febc5939b18d3e6c459c8564c12389c10cc2346678060327235437c23c3", "MacAddress": "02:42:c0:a8:00:02", "IPv4Address": "192.168.0.2/16", "IPv6Address": "" }, "99c0df5990a5ec9d78fc392eb0ee698d00f320e387b5a66d05782ea2013ac3a1": { "Name": "tomcat-net-03", "EndpointID": "41c4e5a4f2f5712a3a070e5337aa80021e8c13844cac1243aa1d8b371cb1679e", "MacAddress": "02:42:c0:a8:00:04", "IPv4Address": "192.168.0.4/16", "IPv6Address": "" }, "cb12e21c37b83c38d894cca0a3b55816aebca90ba8b3b083289f28608d70a566": { "Name": "tomcat-net-02", "EndpointID": "ba491227f9a347145718fd051ff461aa1bd7200c66cacf3397a5a915a86e52a3", "MacAddress": "02:42:c0:a8:00:03", "IPv4Address": "192.168.0.3/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ] -
通过ip和容器名称进行ping的测试
- 我们自定义网络docker都已经帮我们维护好了对应的关系,推荐我们平时这样使用网络
- 好处:
- 可以将不同的集群间建立不同的子网进行隔离,互不干扰
-
-
网络联通
-
实际上是我们的自定义网络中两个不同的自网络之间的打通
-
测试下面的例程
-
解决方法:
-
-
-
Docker network conmect mynet tomcat01- 通过上图我们发现 tomcat01有两个ip 在docker0下的ip是172.17.0.1,在mynet下的IP是192.168.0.5,这个和阿里云的网络很像,在公网中121.199.122.222(公网ip),而172.186.11.1(就是私网ip),解释了一个容器两个IP的问题
-
测试结果
-
-
实战Redis集群
-
搭建redis的集群
-
第一步:创建子网
docker network create redis --subnet 172.38.0.0/16 -
第二步:使用shell脚本构建redis的节点
-
for port in $(seq 1 6);\ do \ mkdir -p /mydata/redis/node-${port}/conf touch /mydata/redis/node-${port}/conf/redis.conf cat << EOF >> /mydata/redis/node-${port}/conf/redis.conf port 6379 bind 0.0.0.0 cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 cluster-announce-ip 172.38.0.1${port} cluster-announce-port 6379 cluster-announce-bus-port 16379 appendonly yes EOF done
-
-
第三步:设置容器(自定义网络、卷映射、端口等)
-
# 将下面的红色数字替换成相应的1~6的序号就行 docker run -p 6376:6379 -p 16676:16379 --name redis-6 -v /mydata/redis/node-6/data:/data -v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
-
-
第四步:进入redis的某一台机器
-
docker exec -it redis-1 /bin/sh #redis默认没有bash
-
-
第五步:创建集群,构建节点
-
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
-
-
测试搭建结果
-
-