[root@server1 harbor]# docker-compose down 为了实验效果,先将所有镜像删除 [root@server1 harbor]# docker network prune 关闭不常用网络 [root@server1 harbor]# docker network ls 剩下的就是docker默认网络 NETWORK ID NAME DRIVER SCOPE e014ad524f8c bridge bridge local docker原身网络 595de9c635c6 host host local docker原身网络 8f69944486a3 none null local docker原身网络docker网络模式默认是桥接模式:
[root@server1 harbor]# ip addr 容器地址是单调递增的,所以容器的ip地址是会变的是动态的
[root@server1 harbor]# yum install bridge-utils -y 安装桥接指令 [root@server1 ~]# docker run -d --name nginx nginx 运行容器 [root@server1 ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.02429831a7e5 no vethcd9db6c 可以发现nginx容器已经桥接到docker0上了 [root@server1 ~]# docker run -d --name nginx2 nginx 再次开启一个容器 [root@server1 ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.02429831a7e5 no vethcd9db6c 可以发现也桥接到docker0上了 vethf80cb76 [root@server1 ~]# curl 172.17.0.2 访问第一个容器ip 地址 ,容器ip地址是单调递增的Welcome to nginx! html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } [root@server1 ~]# curl 172.17.0.3 访问第二个容器ip 地址,容器ip地址是单调递增的 Welcome to nginx!
桥接模式的缺点:
如果可以让外网访问容器需要通过主机的NAT规则才可以访问外网
[root@server1 ~]# docker rm -f nginx2 nginx2 [root@server1 ~]# docker run -d --name demo --network host nginx 运行容器,并指定网络模式为主机模式 8e4292d9fc16394dc271ad01675c5fc37d3aa44f1abf1ad7ecde6c44d662c11e 注意:host网络模式,宿主机ip地址和容器ip地址是共享的 [root@server1 ~]# curl 172.25.50.1 访问宿主机ip地址,就可以访问到容器nginx,ip地址是共享的Welcome to nginx! [root@server1 ~]# docker run -d --name demo2 --network host nginx 再次运行一个host模式容器 [root@server1 ~]# docker ps 查看容器是否运行,容器demo2没有运行 ConTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8e4292d9fc16 nginx "/docker-entrypoint.…" 13 minutes ago Up 13 minutes demo 85e88ed124bc nginx "/docker-entrypoint.…" 33 minutes ago Up 33 minutes 80/tcp nginx [root@server1 ~]# docker logs demo2 查看demo2日志,发现80端口已经被占用
造成上述原因是因为host网络模型是用同一个网络栈,会造成容器之间的网络争抢,所以80端口只能让一个容器使用
[root@server1 ~]# docker rm demo2 删除demo2 demo2 [root@server1 ~]# docker run -it --rm --network none busybox 以none网络模式运行容器 / # ip addr 可以运行 1: lo:2、doker自定义网络 创建自定义网桥mtu 65536 qdisc noqueue qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 但是ip地址 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever / #
[root@server1 ~]# docker network create my_net1 64c6a33f42c0a22628c2b22456c495fd3c316a3571af1594091a45258b17127b [root@server1 ~]# docker network ls
[root@server1 ~]# docker rm -f nginx 删除之前容器 nginx [root@server1 ~]# docker rm -f demo 删除之前容器 demo [root@server1 ~]# docker run -d --name web1 nginx 运行容器,用默认桥接方式 d03446624523b95d630a90f240b772d16b3b089b825db08bd3e64fb9c258bbfb [root@server1 ~]# brctl show bridge name bridge id STP enabled interfaces br-64c6a33f42c0 8000.0242457e59ec no docker0 8000.02429831a7e5 no vethefd382f 默认桥接方式 [root@server1 ~]# docker run -d --name web2 --network my_net1 nginx 运行容器,选者自定义桥接方式 d860d5bbac1cd40469d0f353c3d0cc33fc3a8db3784a82b7b2776e54e1475145 [root@server1 ~]# brctl show 查看 bridge name bridge id STP enabled interfaces br-64c6a33f42c0 8000.0242457e59ec no vethd8b409d 自定义桥接方式 docker0 8000.02429831a7e5 no vethefd382f [root@server1 ~]# docker run -it --rm busybox 运行交互式容器 / # ping web1 可以发现默认桥接方式不可以ping 通主及名web1 ping: bad address 'web1' / # ping 172.25.50.2 只能ping通ip地址 PING 172.25.50.2 (172.25.50.2): 56 data bytes 64 bytes from 172.25.50.2: seq=0 ttl=63 time=0.950 ms 64 bytes from 172.25.50.2: seq=1 ttl=63 time=0.391 ms [root@server1 ~]# docker run -it --rm --network my_net1 busybox 运行容器,用自定义桥接模式 / # ping web2 自定义桥接模式提供解析,可以ping通web2容器名 PING web2 (172.18.0.2): 56 data bytes 64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.127 ms 此时获取的web2地址为172.18.0.2 64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.066 ms [root@server1 ~]# docker stop web2 停止web2 web2 [root@server1 ~]# docker run -d --name web3 --network my_net1 nginx 再次运行,同样以network模式 root@server1 ~]# docker start web2 再次启动web2 web2 [root@server1 ~]# docker run -it --rm --network my_net1 busybox 运行 / # ping web2 PING web2 (172.18.0.3): 56 data bytes 64 bytes from 172.18.0.3: seq=0 ttl=64 time=0.109 ms 此时可以发现web2地址从172.18.0.2变成172.18.0.3了 64 bytes from 172.18.0.3: seq=1 ttl=64 time=0.065 ms
自定义桥接也可以固定ip创建
[root@server1 ~]# docker network create --subnet 172.20.0.0/24 --gateway 172.20.0.1 my_net2 --subnet 表示子网段 -gateway网关 3e8cdb823759f6e0e5f7fe4519001eaa9b25444f3e3da25c0378c9d9a48904bd [root@server1 ~]# docker run -d --name web4 --network my_net2 --ip 172.20.0.100 nginx 运行并创建容器 ,可以指定容器ip,注意--ip只适合有--subnet,-gateway的条件 ed506c0edc25dc83471457b498d639a7ecd2477d87dc8d0cebb8f7b98905bbbc [root@server1 ~]# docker inspect web4 查看容器详细信息
[root@server1 ~]# docker stop web4 停止web4 web4 [root@server1 ~]# docker start web4 启动web4 web4 [root@server1 ~]# docker inspect web4 查看容器详细信息,可以发现容器ip地址没有变化如何让不同网桥的容器通信?
如何让web3和web4网络互通了?
[root@server1 ~]# docker network connect my_net1 web4 相当于给web4添加了一快网卡
相当于一个容器有两块网卡,一个网卡连接一个不通vlan他们之间是可以互通的
[root@server1 ~]# docker pull radial/busyboxplus 拉取busyboxplus [root@server1 ~]# docker tag radial/busyboxplus:latest busyboxplus:latest 改名字 [root@server1 ~]# docker rmi radial/busyboxplus:latest 删除原始的 [root@server1 ~]# docker run -it --rm --network container:web3 busyboxplus container:web3 表示此容器和指定的web3容器共享一个网络栈 / # ip addr 可以发现共享了容器web3的ip地址
/ # curl localhost 可以使用localhost高速快速通信link网络模式 可以用来链接两个容器Welcome to nginx!
[root@server1 ~]# docker run -it --rm --link web1:nginx (此处nginx是起的容器别名)busyboxplus link模式不支持指定义网络,用于默认网络 / # env link模式自动添加了变量 HOSTNAME=aba29e480314 SHLVL=1 HOME=/ NGINX_ENV_PKG_RELEASE=1~bullseye NGINX_PORT_80_TCP=tcp://172.17.0.2:80 NGINX_ENV_NGINX_VERSION=1.21.5 NGINX_ENV_NJS_VERSION=0.7.1 TERM=xterm PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin NGINX_PORT=tcp://172.17.0.2:80 NGINX_NAME=/bold_aryabhata/nginx PWD=/ NGINX_PORT_80_TCP_ADDR=172.17.0.2 NGINX_PORT_80_TCP_PORT=80 NGINX_PORT_80_TCP_PROTO=tcp / # ping nginx link模式可以用别名来访问 PING nginx (172.17.0.2): 56 data bytes 64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.148 ms 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.073 ms / # ping web1 也可以用容器名来访问 PING web1 (172.17.0.2): 56 data bytes 64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.128 ms 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.101 ms / # cat /etc/hosts 因为link模式自动给web1、nginx加了解析了 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 nginx d03446624523 web1 172.17.0.3 aba29e480314 [root@server1 ~]# docker stop web1 关闭web1容器 web1 [root@server1 ~]# docker run -d nginx 创建运行一个容器 [root@server1 ~]# docker start web1 再次打开web1容器 web1 [root@server1 ~]# docker inspect web1 查看web1容器详细信息,发现容器ip地址由原来的172.17.0.2变成172.17.0.3了
[root@server1 ~]# docker run -it --rm --link web1:nginx busyboxplus / # ping web1 PING web1 (172.17.0.3): 56 data bytes ip地址变成了172.17.0.3 64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.125 ms / # cat /etc/hosts3、容器通信原理
容器网关连接docker0,docker0和eth0在同一个宿主机,但是彼此之间网段不一样,需要通过linux内核进行地址转发,然后直接从eth0出去
[root@server1 ~]# docker ps -aq 查看所有容器 3d45355536bd ed506c0edc25 3667fb786338 1c4ad45c1553 d03446624523 9a3f7a47740b [root@server1 ~]# docker rm -f ' docker ps -aq ' 删除所有容器 [root@server1 ~]# docker run -d --name demao -p80:80 nginx 运行容器,建立端口映射 dace0215b173b3650f4e41e88a2bd9d4659bceecd8f35f4337b30e11c44911f6 [root@server1 ~]# iptables -t nat -nL
当外部访问本机的80,会定向到容器的80,这样外部就可以访问容器
测试: [root@server1 ~]# curl 172.25.50.1 直接访问本机,就会定向到容器端口映射和docker-proxy是docker的冗余机制,存在一种即可Welcome to nginx! 但是即使把端口映射删除了,外部也可以访问容器,因为查看进程可以发现有个docker-proxy代理进行,此代理可以负责地址转发 [root@server1 ~]# netstat -antlp
测试:
两个容器之间的通讯 ,因为两个容器都在一个vlan,都在本机 [root@server1 ~]# docker run -it --rm busyboxplus / # ip addr 1: lo:mtu 65536 qdisc noqueue 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 8: eth0@if9: mtu 1500 qdisc noqueue link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0 此容器的ip为172.17.0.3 valid_lft forever preferred_lft forever / # ping 172.17.0.2 访问之前建立的nginx容器,可以ping通 PING 172.17.0.2 (172.17.0.2): 56 data bytes 64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.156 ms 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.069 ms 外部主机访问容器: [root@server1 ~]# iptables -t nat -F 把nat策略全部刷掉,DNAT端口映射也没有了 [root@server1 ~]# iptables -t nat -nL Chain PREROUTING (policy ACCEPT) target prot opt source destination 没有策略了 Chain INPUT (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination [root@server1 ~]# docker run -it --rm busyboxplus / # ping 172.17.0.2 容器之间还是可以ping通的 PING 172.17.0.2 (172.17.0.2): 56 data bytes 64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.112 ms 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.108 ms [root@server1 ~]# ps ax
[root@server1 ~]# kill 3989 杀掉docker-proxy进程,此时DNAT策略和docker-proxy代理都没有了 [root@server1 ~]# docker run -it --rm busyboxplus / # ip addr 10: eth0@if11:4、跨主机容器网络mtu 1500 qdisc noqueue link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0 容器ip变成172.17.0.4 valid_lft forever preferred_lft forever / # ping 172.17.0.2 容器之间访问还是可以访问的,因为在同一个本机,同一个网桥上 PING 172.17.0.2 (172.17.0.2): 56 data bytes 64 bytes from 172.17.0.2: seq=0 ttl=64 time=0.128 ms 64 bytes from 172.17.0.2: seq=1 ttl=64 time=0.078 ms [root@foundation50 network-scripts]# curl 172.25.50.1 外部访问,就不通了,80端口过不去,因为docker-proxy进程被杀掉了 curl: (7) Failed to connect to 172.25.50.1 port 80: Connection refused 恢复iptables策略 [root@server1 ~]# systemctl restart docker 重启doaker引擎 [root@server1 ~]# iptables -t nat -nL 查看防火墙策略已经生效 Chain PREROUTING (policy ACCEPT) target prot opt source destination DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL [root@foundation50 network-scripts]# curl 172.25.50.1 此时外部访问就可以 Welcome to nginx! [root@server1 ~]# ps ax | grep proxy 此时proxy代理也出来了 4750 ? Sl 0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.17.0.2 -container-port 80 4824 pts/0 S+ 0:00 grep --color=auto proxy 现在把防火墙刷掉,只留proxy [root@server1 ~]# iptables -t nat -F 刷掉所有防火墙策略,保留docker-proxy策勒 [root@foundation50 network-scripts]# curl 172.25.50.1 外部访问容器,还可以访问,所以docker-proxy负责外部访问容器 Welcome to nginx! html { color-scheme: light dark; } 现在把proxy杀掉,保留防火强 [root@server1 ~]# systemctl restart docker 再次重启docker,恢iptables策略 [root@server1 ~]# docker start demao 启动容器 demao [root@server1 ~]# kill 5101 杀掉proxy [root@foundation50 network-scripts]# curl 172.25.50.1 外部访问容器,也可以访问; DNAT策略也可以实现外部访问容器 Welcome to nginx! html { color-scheme: light dark; } 宗上所述,上述两种机制存在一种就可以保证外部主机可以访问容器
实验之前清理环境: [root@server1 ~]# docker rm -f demao 删除容器 demao [root@server1 ~]# docker network prune 删除不用的网络 WARNING! This will remove all custom networks not used by at least one container. Are you sure you want to continue? [y/N] y Deleted Networks: my_net1 my_net2 [root@server1 ~]# docker volume prune 删除不用的卷 [root@server1 ~]# docker image prune 删除不用的卷 [root@server1 ~]# docker container prune 删除所有停止的容器 [root@server1 ~]# docker network ls 网络模式 NETWORK ID NAME DRIVER SCOPE aac988c7d96a bridge bridge local 595de9c635c6 host host local 8f69944486a3 none null local
在server1、server2上各添加一块网卡
[root@server1 ~]# ip link set eth1 promisc on 在server1上打开eth1的混杂模式 [root@server1 ~]# ip addr promisc混杂模式已经添加
[root@server1 ~]# ip link set up eth1 激活网卡
[root@server2 ~]# ip link set eth1 promisc on 在server2上打开 eth1混杂模式 [root@server2 ~]# ip link set up eth1 激活网卡 [root@server1 ~]# docker network create -d macvlan --subnet 10.0.0.0/24 --gateway 10.0.0.1 -o parent=eth1 mynet1 自定义创建以macvlan虚拟化技术的mynet1网络模式, -d表示指定驱动 -o表示指定父级网卡 parent父级的意思 523ef6d5d33681b9caacf5118512eee3f8132c9cc03cf6f94ebffa4a16200a66 [root@server1 ~]# docker network ls
[root@server1 ~]# docker run -it --rm --network mynet1 --ip 10.0.0.10 busyboxplus 运行容器,以mynet1 模式运行 / # ip addr 1: lo:mtu 65536 qdisc noqueue 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 17: eth0@if16: mtu 1500 qdisc noqueue link/ether 02:42:0a:00:00:0a brd ff:ff:ff:ff:ff:ff inet 10.0.0.10/24 brd 10.0.0.255 scope global eth0 valid_lft forever preferred_lft forever 在server2上同样操作: [root@server2 ~]# docker network create -d macvlan --subnet 10.0.0.0/24 --gateway 10.0.0.1 -o parent=eth1 mynet1 3879e795cdb7462547fdd7308d2f0e9aded47a23e47cef67b9bf52753199ca8b [root@server2 ~]# docker network ls
[root@server2 ~]# docker run -it --rm --network mynet1 --ip 10.0.0.11 busybox 以mynet1网络方式 / # ip addr 1: lo:macvlan模式容器接口直接与主机网卡连接,无需NAT端口映射和docker-proxymtu 65536 qdisc noqueue 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 5: eth0@if4: mtu 1500 qdisc noqueue link/ether 02:42:0a:00:00:0b brd ff:ff:ff:ff:ff:ff inet 10.0.0.11/24 brd 10.0.0.255 scope global eth0 ip地址为10.0.0.11 valid_lft forever preferred_lft forever / # ping 10.0.0.10 ping server1上容器,可以ping通 PING 10.0.0.10 (10.0.0.10): 56 data bytes 64 bytes from 10.0.0.10: seq=0 ttl=64 time=0.583 ms 64 bytes from 10.0.0.10: seq=1 ttl=64 time=0.313 ms / # ping 10.0.0.11 ping本机上的容器也可以ping通 PING 10.0.0.11 (10.0.0.11): 56 data bytes 64 bytes from 10.0.0.11: seq=0 ttl=64 time=0.107 ms 64 bytes from 10.0.0.11: seq=1 ttl=64 time=0.058 ms
测试: [root@server2 ~]# docker run -d --name demo --network mynet1 --ip 10.0.0.11 nginx 在server2上运行nginx容器,mynet1网络模式 0561b0c677af762608227dea093c3e36cbdb16cc328920cd01484c79aa6357bc [root@server1 ~]# docker run -it --rm --network mynet1 --ip 10.0.0.10 busyboxplus 在server1上运行容器,以mynet1网络模式 [root@server1 ~]# docker ps 查看运行的容器 ConTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 202b2b00b24b busyboxplus "/bin/sh" 26 seconds ago Up 24 seconds practical_hawking [root@server1 ~]# docker attach 202b2b00b24b 当容器退出了,也可以附加此容器进入交互模式 / # curl 10.0.0.11 访问server2上的容器 可以访问,他们之间是直通的macvlan模式缺点:会独占主机网卡Welcome to nginx! [root@server2 ~]# netstat -antlp 在server2上查看端口,发现没有80端口,没有docker-proxy Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 3214/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 3328/master tcp 0 0 172.25.50.2:22 172.25.50.250:54976 ESTABLISHED 3724/sshd: root@pts tcp6 0 0 :::22 :::* LISTEN 3214/sshd tcp6 0 0 ::1:25 :::* LISTEN 3328/master [root@server2 ~]# iptables -t nat -nL 查看火墙策略,发现没有DNAT
[root@server1 ~]# docker network create -d macvlan --subnet 20.0.0.0/24 --gateway 20.0.0.1 -o parent=eth1.1 mynet2 c6bae3603c46dff911977d58ce54c388237756abcb8a5b292172192a8329df56 [root@server2 ~]# docker network create -d macvlan --subnet 20.0.0.0/24 --gateway 20.0.0.1 -o parent=eth1.1 mynet2 [root@server1 ~]# docker run -d --network mynet2 nginx 运行容器,以mynet2网络模式 [root@server1 ~]# docker ps ConTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6c9de2935997 nginx "/docker-entrypoint.…" about a minute ago Up about a minute magical_chaum 容器已经运行 202b2b00b24b busyboxplus "/bin/sh" 26 minutes ago Up 26 minutes practical_hawking [root@server1 ~]# docker inspect 6c9de2935997 查看容器详细信息,分到的ip地址为20.0.0.2
[root@server1 ~]# docker network create -d macvlan --subnet 30.0.0.0/24 --gateway 30.0.0.1 -o parent=eth1.2 mynet3 然后按此方法以此类推建立多macvlan网络 dda0c0cd1bcf8fb2fa478cac292621e9476e5cf6fa843bf72ba048b1e54c8afa [root@server1 ~]# docker network ls 查看docker网络



