docker网络

容器之间网络互通

测试

理解Docker0

准备工作:清空所有的容器,清空所有的镜像

docker rm -f $(docker ps -a -q) # 删除所有容器
docker rmi -f $(docker images -qa) # 删除全部镜像

查看本地ip

ip addr

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    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 qlen 1000
    link/ether 00:16:3e:06:a8:72 brd ff:ff:ff:ff:ff:ff
    inet 172.21.30.251/18 brd 172.21.63.255 scope global dynamic eth0
       valid_lft 314755323sec preferred_lft 314755323sec
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN 
    link/ether 02:42:d3:48:f9:bd brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
[root@izj6c22bffydfp7tlrbx7fz ~]# 

lo 127.0.0.1 # 本机回环地址

eth0 172.17.90.138 # 阿里云的私有IP

docker0 172.18.0.1 # docker网桥

问题

Docker 是如何处理容器网络访问的?

容器之间能不能ping通?

 docker run -d -P --name tomcat01 tomcat
# 查看tomcat01的ip地址,docker会给每个容器都分配一个ip!
docker exec -it tomcat01 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
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

#测试linux服务器是否可以ping通容器内的tomcat
 ping 172.18.0.2

原理

每一个安装了Docker的linux主机都有一个docker0的虚拟网卡。这是个桥接网卡,使用了veth-pair 技术!

本来我们的主机有三个网络,启动tomcat之后 多了一个网络

# 我们启动了一个tomcat01,主机的ip地址多了一个 123: vethc8584ea@if122
# 然后我们在tomcat01容器中查看容器的ip是 122: eth0@if123
 
 启动一个tomcato2# 然后发现linux主机上又多了一个网卡 125: veth021eeea@if124:
# 我们看下tomcat02的容器内ip地址是 124: eth0@if125:

# 观察现象:
# tomcat --- linux主机 vethc8584ea@if122 ---- 容器内 eth0@if123
# tomcat --- linux主机 veth021eeea@if124 ---- 容器内 eth0@if125
# veth-pair 就是一对的虚拟设备接口,它都是成对出现的。一端连着协议栈,一端彼此相连着。
# 正因为有这个特性,它常常充当着一个桥梁,连接着各种虚拟网络设备!
# “Bridge、OVS 之间的连接”,“Docker 容器之间的连接” 等等,以此构建出非常复杂的虚拟网络
结构,比如 OpenStack Neutron。
 

测试下tomcat01和tomcat02容器间是否可以互相ping通

root@lph ~]# docker exec -it tomcat02 ping 172.18.0.2
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

结论:容器和容器之间是可以互相访问的。

结论: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变化就不行了,那我们 能不能使用服务名访问呢?

# 我们使用tomcat02,直接通过容器名ping tomcat01,不使用ip
[root@lph ~]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known # 发现ping不通
# 我们再启动一个tomcat03,但是启动的时候连接tomcat02

[root@kuangshen ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
a3a4a17a2b707766ad4f2bb967ce1d94f658cd4cccef3bb8707395cdc71fa1e7
# 这个时候,我们就可以使用tomcat03 ping通tomcat02 了
[root@kuangshen ~]# 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@kuangshen ~]# docker exec -it tomcat03 ping tomcat01
ping: tomcat01: Name or service not known
# 再来测试,tomcat02 是否可以ping tomcat03 反向也ping不通
[root@kuangshen ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known

思考,这个原理是什么呢?我们进入tomcat03中查看下host配置文件

[root@kuangshen ~]# docker exec -it tomcat03 cat /etc/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.18.0.3 tomcat02 b80da266a3ad # 发现tomcat2直接被写在这里
172.18.0.4 a3a4a17a2b70
# 所以这里其实就是配置了一个 hosts 地址而已!
# 原因:--link的时候,直接把需要link的主机的域名和ip直接配置到了hosts文件中了。

--link早都过时了,我们不推荐使用!我们可以使用自定义网络的方式

自定义网络

1、命令

#查看docker network相关命令
docker network --help

docker network ls
NETWORK ID    NAME  DRIVER   SCOPE
4eb2182ac4b2 bridge bridge   local
ae2b6209c2ab host   host     local
c037f7ec7e57 none   null     local

所有的网路模式

查看一个具体的网络的详细信息

docker network inspect 4eb2182ac4b2

2、自定义网卡

使用命令docker run -d-P--name tomcat01 tomcat启动容器实际默认使用的是--net bridge

,而这个就是我们的docker0,所以也就是相当于执行了

docker run -d-P--name tomcat01 --net bridge tomcat

而docker0 特点是默认的网络,不能通过域名访问,可以通过--link打通但是比较麻烦所以需要我们自定义网络

使用默认的bridge网络模式自定义一个网络,如下

docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet

说明

上面语句就是创建了一个网络 这个网络名字是mynet

--subnet 192.168.0.0/16 创建子网,16表示能创建6553个子网从192.168.0.2到192.168.255.255 如果是24表示255个子网

--gateway 192.168.0.1 配置路由,也即网关,家里所有路由器就是这个地址

查看

docker net inspect mynet

使用自己的网络

docker run -d -P --name tomcat01 --net mynet tomcat

docker run -d -P --name tomcat02 --net mynet tomcat

启动之后查看自定义网络

docker network inspect mynet

docker默认docker0是ping不同容器名的

但是现在使用自定义网络

docker exec -it tomcat01 ping 192.168.0.3
docker exec -it tomcat01 ping tomcat02

可以发现无论通过ip还是容器名都是能ping通的,现在不使用--link也可以ping容器名字了

网络连通

docker0和自定义网络肯定不通,我们使用自定义网络的好处就是网络隔离:大家公司项目部署的业务都非常多,假设我们有一个商城,我们会有订单业务(操作不同数据),会有订单业务购物车业务(操作不同缓存)。如果在一个网络下,有的程序猿的恶意代码就不能防止了,所以我们就在部署的时候网络隔离,创建两个桥接网卡,比如订单业务(里面的数据库,redis,mq,全部业务都在order-net网络下)其他业务在其他网络。那关键的问题来了,如何让 tomcat-net-01 访问 tomcat1?

连接一个容器到一个网络

命令 docker network connect [OPTIONS] NETWORK CONTAINE
docker network connect mynet tomcat01
docker network inspect mynet

tomcat01 可以ping通了

docker exec -it tomcat01 ping tomcat-net-01

结论:如果要跨网络操作别人,就需要使用docker network connect [OPTIONS] NETWORKCONTAINER连接

部署一个redis集群

# 创建网卡
docker network create redis --subnet 172.38.0.0/16
# 通过脚本创建六个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
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; \
# 启动6个容器
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
# 进入一个redis,注意这里是 sh命令
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
# 连接集群
redis-cli -c
# 查看集群信息
cluster info
# 查看节点
cluster nodes
# set a b
# 停止到存值的容器
# 然后再次get a,发现依旧可以获取值
# 查看节点,发现高可用完全没问题

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序三两行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值