Docker网络
Docker0 Docker 容器间互通
Docker使用Linux桥接(参考《Linux虚拟网络技术》),在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即docker run创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器。
我们在容器内部创建的服务,网络可以互相访问,类似于局域网;
测试:
使用tomcat01—->ping tomcat02
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| [root@iZwz94khotag1q066igytrZ /]# docker exec tomcat01 ping tomcat02 PING tomcat02 (172.17.0.2) 56(84) bytes of data. 64 bytes from tomcat02 (172.17.0.2): icmp_seq=1 ttl=64 time=0.107 ms 64 bytes from tomcat02 (172.17.0.2): icmp_seq=2 ttl=64 time=0.096 ms 64 bytes from tomcat02 (172.17.0.2): icmp_seq=3 ttl=64 time=0.094 ms ^C [root@iZwz94khotag1q066igytrZ /]# docker exec tomcat01 ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.100 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.108 ms 64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.099 ms ^C [root@iZwz94khotag1q066igytrZ /]# docker exec tomcat01 ping 172.17.0.3 PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data. 64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.027 ms 64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.039 ms 64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.038 ms ^C
|
使用tomcat2—->ping tomcat1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| [root@iZwz94khotag1q066igytrZ /]# docker exec tomcat02 ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.028 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.033 ms 64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.041 ms ^C [root@iZwz94khotag1q066igytrZ /]# docker exec tomcat02 ping 172.17.0.3 PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data. 64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.122 ms 64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.114 ms 64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.068 ms 64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.065 ms ^C [root@iZwz94khotag1q066igytrZ /]#
|
我们可以知道,这两个是通的;但是我们不可以使用容器名ping,所以我们需要使用 –link来实现我们的使用容器名字来ping
–link
1
| docker run -d -it --name tomcat01 --link tomcat02 tomcat
|
在启动的时候,我们就指定我们要链接的模式,实现二者的互通;
原理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| [root@iZwz94khotag1q066igytrZ /]# docker exec -it tomcat01 /bin/bash root@1754afecd1bc:/usr/local/tomcat# lll bash: lll: command not found root@1754afecd1bc:/usr/local/tomcat# ls BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work root@1754afecd1bc:/usr/local/tomcat# cd root@1754afecd1bc:~# cd .. root@1754afecd1bc:/# cd etc root@1754afecd1bc:/etc# cat hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.2 tomcat02 7c064e4efced 172.17.0.3 1754afecd1bc root@1754afecd1bc:/etc#
|
就是类似于我们修改windows下面的etc/host一样,当我们使用名字ping的时候,他会自动转到我们的ip地址;
–link早都过时了,我们不推荐使用!我们可以使用自定义网络的方式
自定义网络
我们先查看我们刚刚部署的网络:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| [root@iZwz94khotag1q066igytrZ /]# docker network ls NETWORK ID NAME DRIVER SCOPE 792301ca29a4 bridge bridge local ab45058093b3 host host local 30427e45134c none null local [root@iZwz94khotag1q066igytrZ /]# docker network inspect 792301ca29a4 [ { "Name": "bridge", "Id": "792301ca29a4b692a35d56dd094e39641569fd9eb45272e8dc1e9d0ea387617d", "Created": "2020-11-30T21:53:10.295778567+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" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "1754afecd1bc8ca03257a622dc25bdb8cb52de8b10fc4f1aa39206ff809d97f4": { "Name": "tomcat01", "EndpointID": "a7738d2aee7d6c32be2959621bbb773d8b06356acdd2030ded082e5c3a8a4b1b", "MacAddress": "02:42:ac:11:00:03", "IPv4Address": "172.17.0.3/16", "IPv6Address": "" }, "7c064e4efced691f955fa9c4a2bfbd24bdc69212e572b5f228020f565ada7948": { "Name": "tomcat02", "EndpointID": "601b92a9d09b78e65eb1551bd3d3b7ff8d0689c81e16dc0cdd1eb35bda0bb6a0", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "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": {} } ]
|
网络配置:
1 2 3 4 5
| "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" }
|
容器的网络连接:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| "Containers": { "1754afecd1bc8ca03257a622dc25bdb8cb52de8b10fc4f1aa39206ff809d97f4": { "Name": "tomcat01", "EndpointID": "a7738d2aee7d6c32be2959621bbb773d8b06356acdd2030ded082e5c3a8a4b1b", "MacAddress": "02:42:ac:11:00:03", "IPv4Address": "172.17.0.3/16", "IPv6Address": "" }, "7c064e4efced691f955fa9c4a2bfbd24bdc69212e572b5f228020f565ada7948": { "Name": "tomcat02", "EndpointID": "601b92a9d09b78e65eb1551bd3d3b7ff8d0689c81e16dc0cdd1eb35bda0bb6a0", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" }
|
发现在这个网络下面有一个名为tomcat01和tomcat02的容器的网络的IP地址;所以,我们要自己创建一个网络的话,如果在后面的container里面显示了我们的网络,子网,我们就部署成功;
第一步,先创建一个属于自己的网络
1
| docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
|
第二步、启动容器服务时使用 –net +网络名绑定网络
1 2
| docker run -d -it --net saxon --name tomcat01 tomcat docker run -d -it --net saxon --name tomcat02 tomcat
|
第三步查看网络状态:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| [root@iZwz94khotag1q066igytrZ docker]# docker network inspect saxon [ { "Name": "saxon", "Id": "ae4d1b67843db37b2b257228148ae45badf5874c72ed677673eac90b3ab7200b", "Created": "2020-12-01T13:41:52.55206052+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": { "5e5d7b74d8bd426e151f6af2fb6aca8330077894be5385faa118b7a9c34f278b": { "Name": "tomcat01", "EndpointID": "e96e3d6a90310960972d569613d19ab97422e13fd55ac5c8847780538df40f49", "MacAddress": "02:42:c0:a8:00:03", "IPv4Address": "192.168.0.3/16", "IPv6Address": "" }, "c438c62aa2dafa22619f712d69c95a09c95dd3c93fac74b7348897c794620f04": { "Name": "tomcat02", "EndpointID": "2780e88e6ff8244c72747294326004d5688049d9be28163d75872e4eb21916d0", "MacAddress": "02:42:c0:a8:00:02", "IPv4Address": "192.168.0.2/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ]
|
发现和我们的Docker0属性一样,我们再在容器内部ping一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #Tomcat1 ping tomcat2 测试通过 [root@iZwz94khotag1q066igytrZ docker]# docker exec -it tomcat01 ping 192.168.0.2 PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data. 64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.157 ms 64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.108 ms 64 bytes from 192.168.0.2: icmp_seq=3 ttl=64 time=0.106 ms ^C --- 192.168.0.2 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 35ms rtt min/avg/max/mdev = 0.106/0.123/0.157/0.026 ms
#tomcat2 ping tomcat1 测试通过 [root@iZwz94khotag1q066igytrZ docker]# docker exec -it tomcat02 ping 192.168.0.3 PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data. 64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.115 ms 64 bytes from 192.168.0.3: icmp_seq=2 ttl=64 time=0.111 ms 64 bytes from 192.168.0.3: icmp_seq=3 ttl=64 time=0.113 ms ^C --- 192.168.0.3 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 50ms rtt min/avg/max/mdev = 0.111/0.113/0.115/0.001 ms
|
到此,我们自己新建的网络成功使用;
实战:搭建redis集群
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| 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
#逐一启动镜像 [root@iZwz94khotag1q066igytrZ redis]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 01994e162878 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 8 seconds ago Up 7 seconds 0.0.0.0:6371->6379/tcp, 0.0.0.0:16371->16379/tcp redis-1 [root@iZwz94khotag1q066igytrZ redis]# docker run -p 6371:6379 -p 16371:16379 --name redis-1 -v /mydata/redis/node-1/data:/data -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf e8f73a2f5b6955842c2c293d06c38da046049fb736d1a39ab3d440cd0739700d docker: Error response from daemon: Address already in use. [root@iZwz94khotag1q066igytrZ redis]# docker run -p 6372:6379 -p 16372:16379 --name redis-2 -v /mydata/redis/node-2/data:/data -v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf docker: Error response from daemon: Conflict. The container name "/redis-2" is already in use by container "e8f73a2f5b6955842c2c293d06c38da046049fb736d1a39ab3d440cd0739700d". You have to remove (or rename) that container to be able to reuse that name. See 'docker run --help'. [root@iZwz94khotag1q066igytrZ redis]# docker rm -f redis-2 redis-2 [root@iZwz94khotag1q066igytrZ redis]# docker run -p 6372:6379 -p 16372:16379 --name redis-2 -v /mydata/redis/node-2/data:/data -v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf efab199dc4d9abfdc0ba37e100894c50cdd4ec470b5a3b61b7184070ccb1036d [root@iZwz94khotag1q066igytrZ redis]# docker run -p 6373:6379 -p 16373:16379 --name redis-3 -v /mydata/redis/node-3/data:/data -v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf c579a0b63d04a874758a7309c8187c248b3a6383d2a76b90d2f2acbe2fc3fdfd [root@iZwz94khotag1q066igytrZ redis]# docker run -p 6374:6379 -p 16374:16379 --name redis-4 -v /mydata/redis/node-4/data:/data -v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf 3e33d8a8b1eb767f1eb0a8bc2b9ca4c6c4f7e65303f7ba18c3baf769b3185b10 [root@iZwz94khotag1q066igytrZ redis]# docker run -p 6375:6379 -p 16375:16379 --name redis-5 -v /mydata/redis/node-5/data:/data -v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf -d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf 1e2080f42235f1b134714f82f7b5555336cb4e87777781bba02e653282018bb3 [root@iZwz94khotag1q066igytrZ redis]# docker run -p 6376:6379 -p 16376: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 35c59360d6fde0b51b0a72d8a4eae5660df75739b43356423b842454455a3288 [root@iZwz94khotag1q066igytrZ redis]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 35c59360d6fd redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:6376->6379/tcp, 0.0.0.0:16376->16379/tcp redis-6 1e2080f42235 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 32 seconds ago Up 31 seconds 0.0.0.0:6375->6379/tcp, 0.0.0.0:16375->16379/tcp redis-5 3e33d8a8b1eb redis:5.0.9-alpine3.11 "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:6374->6379/tcp, 0.0.0.0:16374->16379/tcp redis-4 c579a0b63d04 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:6373->6379/tcp, 0.0.0.0:16373->16379/tcp redis-3 efab199dc4d9 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 0.0.0.0:6372->6379/tcp, 0.0.0.0:16372->16379/tcp redis-2 01994e162878 redis:5.0.9-alpine3.11 "docker-entrypoint.s…" 5 minutes ago Up 5 minutes 0.0.0.0:6371->6379/tcp, 0.0.0.0:16371->16379/tcp redis-1
|
搭建集群:
1 2 3
| 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
|
结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| [root@iZwz94khotag1q066igytrZ redis-6.0.9]# 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 >>> Performing hash slots allocation on 6 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 Adding replica 172.38.0.15:6379 to 172.38.0.11:6379 Adding replica 172.38.0.16:6379 to 172.38.0.12:6379 Adding replica 172.38.0.14:6379 to 172.38.0.13:6379 M: 98d2901b86c5d11dddcd0134a9932b34f0c73f71 172.38.0.11:6379 slots:[0-5460] (5461 slots) master M: ae4526fbe1ead0860de11af4ceb505090545c7df 172.38.0.12:6379 slots:[5461-10922] (5462 slots) master M: c013d07adf4956f0d97a88933ea81daa92ce27c2 172.38.0.13:6379 slots:[10923-16383] (5461 slots) master S: 112777ebdd54a7899c5316f0e037378b827dbee7 172.38.0.14:6379 replicates c013d07adf4956f0d97a88933ea81daa92ce27c2 S: 8ca411149d57455bee0d1f2480195b96e75e9dab 172.38.0.15:6379 replicates 98d2901b86c5d11dddcd0134a9932b34f0c73f71 S: 92d1fb43542e1f7d0a869a57da757d5aaf051079 172.38.0.16:6379 replicates ae4526fbe1ead0860de11af4ceb505090545c7df Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join .... >>> Performing Cluster Check (using node 172.38.0.11:6379) M: 98d2901b86c5d11dddcd0134a9932b34f0c73f71 172.38.0.11:6379 slots:[0-5460] (5461 slots) master 1 additional replica(s) M: ae4526fbe1ead0860de11af4ceb505090545c7df 172.38.0.12:6379 slots:[5461-10922] (5462 slots) master 1 additional replica(s) M: c013d07adf4956f0d97a88933ea81daa92ce27c2 172.38.0.13:6379 slots:[10923-16383] (5461 slots) master 1 additional replica(s) S: 112777ebdd54a7899c5316f0e037378b827dbee7 172.38.0.14:6379 slots: (0 slots) slave replicates c013d07adf4956f0d97a88933ea81daa92ce27c2 S: 92d1fb43542e1f7d0a869a57da757d5aaf051079 172.38.0.16:6379 slots: (0 slots) slave replicates ae4526fbe1ead0860de11af4ceb505090545c7df S: 8ca411149d57455bee0d1f2480195b96e75e9dab 172.38.0.15:6379 slots: (0 slots) slave replicates 98d2901b86c5d11dddcd0134a9932b34f0c73f71 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
|
查看一个客户端里面的集群信息:
1 2 3 4 5 6 7 8 9 10 11 12 13
| 127.0.0.1:6379> info replication # Replication role:master connected_slaves:1 slave0:ip=172.38.0.1,port=6379,state=online,offset=140,lag=1 master_replid:975f974a938905b155fa316b0d0f57e795e57cca master_replid2:0000000000000000000000000000000000000000 master_repl_offset:140 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:140
|
发现创建集群成功;
这个集群于哨兵模式不一样的是,一个主机对应一个从机,但是我们的从机也具有写的权限;
我们在设置值的时候:
1 2 3
| 127.0.0.1:6379> set k1 v1 -> Redirected to slot [12706] located at 172.38.0.13:6379 OK
|
同样的,当主机挂掉以后,我们的从机会变成主机,主机也会变成从机;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| [root@iZwz94khotag1q066igytrZ redis-6.0.9]# docker exec -it redis-3 /bin/sh /data # redis-cli 127.0.0.1:6379> info replication # Replication role:slave master_host:172.38.0.14 master_port:6379 master_link_status:up master_last_io_seconds_ago:7 master_sync_in_progress:0 slave_repl_offset:1173 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:b5c59e51eb3cd20d10b4eddc83dd3fb444501479 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1173 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1104 repl_backlog_histlen:70 127.0.0.1:6379>
|
我们把原来的主机挂掉,然后在创建一个容器,再用同样的办法创建一个主机,发现主机变成从机;