作者:@郑琰
本文转载请注明出处!:https://www.cnblogs.com/zhengyan6/p/16191402.html
理解docker0
| docker rm -f $(docker ps -a -q) |
| docker rmi -f $(docker images -qa) |
Docker的网络也是十分重要的一个点
查看本地IP
ip a

| |
| lo 127.0.0.1 |
| eth0 172.17.90.138 |
| docker0 172.18.0.1 |
| |
测试
docker会给每个容器都分配一个ip,且容器和容器之间是可以互相访问的
| |
| [root@zheng ~] |
| |
| |
| [root@zheng ~] |
| 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group |
| default qlen 1000 |
| link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 |
| inet 127.0.0.1/8 scope host lo |
| valid_lft forever preferred_lft forever |
| 122: eth0@if123: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue |
| state UP group default |
| link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 |
| inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0 |
| valid_lft forever preferred_lft forever |
| |
| |
| [root@zheng ~] |
| PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data. |
| 64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.070 ms |
| |
原理
- 1,每一个安装了Docker的linux主机都有一个docker0的虚拟网卡。这是个桥接网卡,使用了veth-pair技术!
下面总结有理解veth-pair技术
| # 我们再次查看主机的 ip addr |
| [root@zheng ~]# ip addr |
| 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 |
| link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo |
| valid_lft forever preferred_lft forever |
| 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 |
| link/ether 00:16:3e:30:27:f4 brd ff:ff:ff:ff:ff:ff |
| inet 172.17.90.138/20 brd 172.17.95.255 scope global dynamic eth0 valid_lft 310954997sec preferred_lft 310954997sec |
| 3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default |
| link/ether 02:42:bb:71:07:06 brd ff:ff:ff:ff:ff:ff |
| inet 172.18.0.1/16 brd 172.18.255.255 scope global docker0 valid_lft forever preferred_lft forever |
| 123: vethc8584ea@if122: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc |
| noqueue master docker0 state UP group default |
| link/ether 0a:4b:bb:40:78:a7 brd ff:ff:ff:ff:ff:ff link-netnsid 0 |
| |
| # 发现:本来我们有三个网络,我们在启动了个tomcat容器之后,多了一个!123的网络! |
- 2,每启动一个容器,linux主机就会多了一个虚拟网卡
| |
| |
| |
| |
| [root@zheng ~] |
| |
| |
| |
| [root@zheng ~] |
| |
| |
| |
| |
| |
| |
| |
| |
| |
- 3,测试下tomcat01和tomcat02容器间是否可以互相ping通
| [root@zheng ~] |
| PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data. |
| 64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.110 ms |
| |
| |
- 4,网络模型图

结论:tomcat1和tomcat2共用一个路由器。是的,他们使用的一个,就是docker0。任何一个容器启动默认都是docker0网络。
docker默认会给容器分配一个可用ip。
总结
Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容
器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,
这样容器之间就能够通过容器的Container-IP直接通信。

Docker容器网络就很好的利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth-pair);
Docker中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高(因为Linux是在内核中进行数据的复制来实现虚拟接口之间的数据转发,
无需通过外部的网络设备交换),对于本地系统和容器系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多。
容器互联--Link
思考一个场景,我们编写一个微服务,数据库连接地址原来是使用ip的,如果ip变化就不行了,那我们能不能使用服务名访问呢?
jdbc:mysql://mysql:3306,这样的话哪怕mysql重启,我们也不需要修改配置了!docker提供了 --link 的操作!
| # 我们使用tomcat02,直接通过容器名ping tomcat01,不使用ip |
| [root@zheng ~]# docker exec -it tomcat02 ping tomcat01 |
| ping: tomcat01: Name or service not known |
| # 发现ping不通 |
| |
| # 我们再启动一个tomcat03,但是启动的时候连接tomcat02 |
| [root@zheng ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat |
| a3a4a17a2b707766ad4f2bb967ce1d94f658cd4cccef3bb8707395cdc71fa1e7 |
| |
| # 这个时候,我们就可以使用tomcat03 ping通tomcat02 了 |
| [root@zheng ~]# docker exec -it tomcat03 ping tomcat02 |
| PING tomcat02 (172.18.0.3) 56(84) bytes of data. |
| 64 bytes from tomcat02 (172.18.0.3): icmp_seq=1 ttl=64 time=0.093 ms |
| 64 bytes from tomcat02 (172.18.0.3): icmp_seq=2 ttl=64 time=0.066 ms |
| |
| # 再来测试,tomcat03 是否可以ping tomcat01 失败 |
| [root@zheng ~]# docker exec -it tomcat03 ping tomcat01 |
| ping: tomcat01: Name or service not known |
| |
| # 再来测试,tomcat02 是否可以ping tomcat03 发现也ping不通 |
| [root@zheng ~]# docker exec -it tomcat02 ping tomcat03 |
| ping: tomcat03: Name or service not known |
- 思考,这个原理是什么呢?我们进入tomcat03中查看下host配置文件
| [root@zheng ~] |
| 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.18.0.3 tomcat02 b80da266a3ad |
| 172.18.0.4 a3a4a17a2b70 |
| |
| |
| |
--link早都过时了,我们不推荐使用!我们可以使用自定义网络的方式
自定义网络
基本命令查看
docker network --help

| [root@zheng ~]# docker network ls |
| NETWORK ID NAME DRIVER SCOPE |
| 4eb2182ac4b2 bridge bridge local |
| ae2b6209c2ab host host local |
| c037f7ec7e57 none null local |
| #1、网络驱动 |
| Docker 网络子系统使用可插拔的驱动,默认情况下有多个驱动程序,并提供核心联网功能。 |
| |
| (1)bridge:桥接网络,这是默认的网络驱动程序(不指定驱动程序创建的容器默认是bridge驱动)。 |
| (2)host:主机网络。消除容器和主机的网络隔离,直接使用主机的网络。 |
| (3)overlay:覆盖网络。可以将多个Docker守护进程连接,实现跨主机容器通讯(swarm集群)。 |
| (4)macvlan:将MAC地址分配给容器,使容器作为网络上的物理设备。不通过Docker主机网络栈进行路由,直接通过MAC地址路由到容器。 |
| (5)none:表示关闭容器的所有网络连接。常与自定义网络驱动一起使用,不适用于swarm。 |
| (6)网络插件:可以通过Docker安装和使用第三方网络插件。 |
| |
| #2、Docker 网络驱动选用原则 |
| (1)bridge桥接网络:最适合用于同一个Docker主机上运行的多个容器之间需要通信的场景。(单主机) |
| (2)host主机网络:最适用于当网络栈不能与Docker主机隔离,而容器的其他方面需要被隔离的场景。(解除容器和主机隔离) |
| (3)overlay网络:适用于不同Docker主机上运行的容器需要通信的场景,或者多个应用程序通过Swarm集群服务一起工作的场景。(多主机、集群) |
| (4)macvlan网络:适用于从虚拟机迁移过来的场景,或者容器需要像网络上的物理机一样,拥有独立MAC地址的场景。(容器需要mac) |
| (5)第三方网络插件适用于将Docker与专用网络栈进行集成的场景。(订制化) |

| |
| 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 |
| --gateway 192.168.0.1 |
| |
| |
| docker network ls |
| |
| |
| docker network inspect mynet(或ID) |

自定义网卡
1、删除原来的所有容器
| [root@zheng ~]# docker rm -f $(docker ps -aq) |
| |
| # 恢复到了最开始的样子 |
| [root@zheng ~]# ip addr |
| 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group |
| default qlen 1000 |
| link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 |
| inet 127.0.0.1/8 scope host lo |
| valid_lft forever preferred_lft forever |
| 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 |
| link/ether 00:16:3e:30:27:f4 brd ff:ff:ff:ff:ff:ff |
| inet 172.17.90.138/20 brd 172.17.95.255 scope global dynamic eth0 valid_lft 310951436sec preferred_lft 310951436sec |
| 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default |
| link/ether 02:42:bb:71:07:06 brd ff:ff:ff:ff:ff:ff |
| inet 192.168.0.1/16 brd 192.168.255.255 scope global docker0valid_lft forever preferred_lft forever |
2、创建容器,但是默认创建的容器都是docker0网卡的
| # 默认我们不配置网络,也就相当于默认值 --net bridge 使用的docker0 |
| docker run -d -P --name tomcat01 --net bridge tomcat |
| |
| # docker0网络的特点 |
| 1.它是默认的 |
| 2.域名访问不通 |
| 3.--link 域名通了,但是删了又不行 |
3、可以在容器创建的时候使用自定义网络
| |
| |
| [root@zheng ~] |
| 09bd09d8d3a6b33e6d19f49643dab551e5a45818baf4d5328aa7320c6dcfc236 |
| |
| |
| [root@zheng ~] |
| NETWORK ID NAME DRIVER SCOPE |
| 4eb2182ac4b2 bridge bridge local |
| ae2b6209c2ab host host local |
| 09bd09d8d3a6 mynet bridge local |
| c037f7ec7e57 none null local |
| [root@zheng ~] |
| [ |
| { |
| "Name": "mynet", |
| "Id": |
| "09bd09d8d3a6b33e6d19f49643dab551e5a45818baf4d5328aa7320c6dcfc236", |
| "Created": "2020-05-13T13:29:33.568644836+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@zheng ~] |
| 065f82e947c760c63539ab4c0de0d683787ec7ac6d0dcaa71f64e191319f9fe7 |
| |
| [root@zheng ~] |
| 2e85d71afe87c87166786b0bbae2d90eefb969d716fcd78a21173add5956cb12 |
| |
| [root@zheng ~] |
| CONTAINER ID IMAGE PORTS NAMES |
| 2e85d71afe87 tomcat 0.0.0.0:32772->8080/tcp tomcat-net-02 |
| 065f82e947c7 tomcat 0.0.0.0:32771->8080/tcp tomcat-net-01 |
| |
| |
| [root@zheng ~] |
| [ |
| { |
| "Name": "mynet", |
| "Id": |
| "09bd09d8d3a6b33e6d19f49643dab551e5a45818baf4d5328aa7320c6dcfc236", |
| ............ |
| "Containers": { |
| |
| "065f82e947c760c63539ab4c0de0d683787ec7ac6d0dcaa71f64e191319f9fe7": { |
| "Name": "tomcat-net-01", |
| "EndpointID": |
| "d61cef1bc294d7f10fb6d9b728735fc87bed79e4e02f5298374f0fab3e9b2da6", |
| "MacAddress": "02:42:c0:a8:00:02", |
| "IPv4Address": "192.168.0.2/16", |
| "IPv6Address": "" |
| }, |
| |
| "2e85d71afe87c87166786b0bbae2d90eefb969d716fcd78a21173add5956cb12": { |
| "Name": "tomcat-net-02", |
| "EndpointID": |
| "adbc37a20526c2985c3589382998a3d106ef722662c7b296a57d8a7c8f449f38", |
| "MacAddress": "02:42:c0:a8:00:03", |
| "IPv4Address": "192.168.0.3/16", |
| "IPv6Address": "" |
| } |
| }, |
| "Options": {}, |
| "Labels": {} |
| } |
| ] |
| |
| |
| [root@zheng ~] |
| 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.093 ms |
| |
| [root@zheng ~] |
| PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data. |
| 64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 |
| time=0.063 ms |
| 64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 |
| time=0.066 ms |
| |
| |
| |
好处:
redis 不同的集群使用不同的网络,保证集群是安全和健康的
mysql 不同的集群使用不同的网络,保证集群是安全和健康的
互相隔离的
网络连通

docker0和自定义网络肯定不通,我们使用自定义网络的好处就是网络隔离:
大家公司项目部署的业务都非常多,假设我们有一个商城,我们会有订单业务(操作不同数据),会有订单业务购物车业务(操作不同缓存)。如果在一个网络下,有的程序猿的恶意代码就不能防止了,所以我们就在部署的时候网络隔离,创建两个桥接网卡,比如订单业务(里面的数据库,redis,mq,全部业务都在order-net网络下)其他业务在其他网络。
那关键的问题来了,如何让 tomcat-net-01 访问 tomcat1?
| |
| [root@zheng ~] |
| bcd122e0dcf6bf8c861eaa934911f98a5497a4954f3fde9575e496160bd23287 |
| |
| [root@zheng ~] |
| 6183aaeca003a3e5a3549a37f9c1040551320ae358807b4aaad547a986afb887 |
| |
| |
| [root@zheng ~] |
| CONTAINER ID IMAGE PORTS NAMES |
| 6183aaeca003 tomcat 0.0.0.0:32774->8080/tcp tomcat02 |
| bcd122e0dcf6 tomcat 0.0.0.0:32773->8080/tcp tomcat01 |
| 2e85d71afe87 tomcat 0.0.0.0:32772->8080/tcp tomcat-net-02 |
| 065f82e947c7 tomcat 0.0.0.0:32771->8080/tcp tomcat-net-01 |
| |
| |
| [root@zheng ~] |
| Commands: |
| connect Connect a container to a network |
| create Create a network |
| disconnect Disconnect a container from a network |
| inspect Display detailed information on one or more networks |
| ls List networks |
| prune Remove all unused networks |
| rm Remove one or more networks |
| |
| |
| |
| |
| [root@zheng ~] |
| [root@zheng ~] |
| [ |
| { |
| ...... |
| "Containers": { |
| |
| "065f82e947c760c63539ab4c0de0d683787ec7ac6d0dcaa71f64e191319f9fe7": { |
| "Name": "tomcat-net-01", |
| "EndpointID": |
| "d61cef1bc294d7f10fb6d9b728735fc87bed79e4e02f5298374f0fab3e9b2da6", |
| "MacAddress": "02:42:c0:a8:00:02", |
| "IPv4Address": "192.168.0.2/16", |
| "IPv6Address": "" |
| }, |
| |
| "2e85d71afe87c87166786b0bbae2d90eefb969d716fcd78a21173add5956cb12": { |
| "Name": "tomcat-net-02", |
| "EndpointID": |
| "adbc37a20526c2985c3589382998a3d106ef722662c7b296a57d8a7c8f449f38", |
| "MacAddress": "02:42:c0:a8:00:03", |
| "IPv4Address": "192.168.0.3/16", |
| "IPv6Address": "" |
| }, |
| // 发现我们的tomcat01就进来这里了,tomcat01拥有了双ip |
| |
| "bcd122e0dcf6bf8c861eaa934911f98a5497a4954f3fde9575e496160bd23287": { |
| "Name": "tomcat01", |
| "EndpointID": |
| "b2bf2342948e17048d872a4d5603c77e90d0e032439d510e86c10a1acc3928d9", |
| "MacAddress": "02:42:c0:a8:00:04", |
| "IPv4Address": "192.168.0.4/16", |
| "IPv6Address": "" |
| } |
| }, |
| ...... |
| } |
| } |
| |
| |
| [root@zheng ~] |
| 64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.071 ms |
| 64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.067 ms |
| |
| |
| [root@zheng ~] |
结论:如果要跨网络操作别人,就需要使用docker network connect [OPTIONS] NETWORK CONTAINER
连接
实战:部署一个Redis集群

| |
| docker network create redis --subnet 172.38.0.0/16 |
| docker network ls 即可看到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} #连接具体IP |
| cluster-announce-port 6379 |
| cluster-announce-bus-port 16379 |
| appendonly yes |
| EOF |
| done |
| |
| cd /mydata/redis/ |
| ls 即可看到六个节点 |
| cat node-1/conf 可看见配置文件内容,即配置成功 |
| |
| |
| docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port} \ |
| -v /mydata/redis/node-${port}/data:/data \ |
| -v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf \ |
| -d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server |
| /etc/redis/redis.conf; \ |
| |
| |
| 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 |
| |
| |
| 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 |
| |
| |
| |
| docker exec -it redis-1 /bin/sh |
| |
| |
| 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 |
| 输入yes |
| |
| |
| |
| redis-cli -c |
| |
| |
| cluster info |
| |
| |
| cluster nodes |
| |
| |
| set a b |
| |
| |
| docker stop redis-3 |
| |
| |
| |
| get a |
| |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)