- 1.docker 网络通讯
结论:tomcat1和tomcat2共用一个路由器。是的,他们使用的一个,就是docker0。任何一个容器启动 默认都是docker0网络。
docker会默认给启动的容器分配一个可用的IP">veth-pair 就是一对的虚拟设备接口,它都是成对出现的。一端连着协议栈,一端彼此相着。
# 正因为有这个特性,它常常充当着一个桥梁,连接着各种虚拟网络设备!
# “Bridge、OVS 之间的连接”,“Docker 容器之间的连接” 等等,以此构建出非常复杂的虚拟网络结构,比如 OpenStack Neutron。
网络模型图
结论:tomcat1和tomcat2共用一个路由器。是的,他们使用的一个,就是docker0。任何一个容器启动 默认都是docker0网络。
docker会默认给启动的容器分配一个可用的IP- 2.docker网络模式修改
- 3.容器通信
- 网络联通实验
- 1.解决办法1
- 2.解决办法2
- 网络空间分类 图表
1.docker 网络通讯
1)docker0
我们来查看一下没有启动任何容器的状态下有几个Ip
查看本机Ip
我们启动一个容器在查看一下网卡
docker run —name tomcat01 -d tomcat
这是为什么?
这是因为一个技术 veth-pair (虚拟网卡技术)
每一个安装了Docker的linux主机都有一个docker0的虚拟网卡。这是个桥接网卡,使用了veth-pair技术!
是为了实现容器间的网络通讯的
原理
我们进入容器内查看一下Ip[root@localhost ~]# docker exec -it tomcat02 ip addr1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group defaultlink/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever
#容器也也有一个Ip 正好使用IP addr 查看的时候也多了一张网卡
结论
veth-pair 就是一对的虚拟设备接口,它都是成对出现的。一端连着协议栈,一端彼此相着。
# 正因为有这个特性,它常常充当着一个桥梁,连接着各种虚拟网络设备!
# “Bridge、OVS 之间的连接”,“Docker 容器之间的连接” 等等,以此构建出非常复杂的虚拟网络结构,比如 OpenStack Neutron。
网络模型图

结论:tomcat1和tomcat2共用一个路由器。是的,他们使用的一个,就是docker0。任何一个容器启动 默认都是docker0网络。
docker会默认给启动的容器分配一个可用的IP
小结
Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),
Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,
同时Docker网桥是每个容器的默认网 关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接 通信。
Docker容器网络就很好的利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并 让他们彼此联通(这样一对接口叫veth pair);
Docker中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高(因为Linux是在内核中 进行数据的复制来实现虚拟接口之间的数据转发,无需通过外部的网络设备交换),对于本地系统和容 器系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多
底层本质
(1) 容器访问外部网络 其实就是在防火墙添加了这样一条规则
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -o docker0 -j MASQUERADE
(2) 外部网络访问容器
docker run -d -p 80:80 apacheiptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKERiptables -t nat -A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.2:80这就是snat 和 dnat 转换
docker0 之间的通讯相当于虚拟机的桥接模式 和外界通讯时NAT
2.docker网络模式修改
1)进程网络修改 (不常用)
这个就是修改守护进程的网络模式 一个容器至少有一个守护进程
但是一个守护进程 可以守护多个容器 守护进程 就是对后台的容器进行实时
的监控 以及 关闭开启等操作 一般使用脚本的方式 里边写入了启动 关闭 的命令
-b, --bridge=”” 指定 Docker 使用的网桥设备,默认情况下 Docker 会自动创建和使用 docker0 网桥设备,
通过此参数可以使用已经存在的设备
--bip 指定 Docker0 的 IP 和掩码,使用标准的 CIDR 形式,如 10.10.10.10/24
--dns 配置容器的 DNS,在启动 Docker 进程是添加,所有容器全部生效
2) 容器网络修改
--dns 用于指定启动的容器的 DNS
--net 用于指定容器的网络通讯方式,有以下四个值
bridge:Docker 默认方式,网桥模式
none:容器没有网络栈
container:使用其它容器的网络栈,Docker容器会加入其它容器的 network namespace
host:表示容器使用 Host 的网络,没有自己独立的网络栈。容器可以完全访问 Host 的网络,不安全
我们不配置网络相当于使用 默认是相当于这条命令
docker run -d -P --name tomcat01 --net bridge tomcat
| ** | ** | ** |
|---|---|---|
| bridge模式 | —net=bridge |
默认值,在Docker网桥docker0上为容器创建新的网络栈 |
| none模式 | —net=none | 不配置网络,用户可以稍后进入容器,自行配置 |
container 模式 |
— net=container:name/id |
容器和另外一个容器共享Network namespace。kubernetes中的pod就是多个容器共享一个Network namespace。 |
| host模式 | —net=host | 容器和宿主机共享Network namespace |
| 用户自定义 | —net=自定义网络 | 用户自己使用network相关命令定义网络,创建容器的时候可以指定为自己定义的网络 |
3) 暴露端口
-p/P 选项的使用格式
第一种:
-P(大) 将容器内部开放的网络端口随机映射到宿主机的一个端口上
第二种:-p指定要映射的端口,一个指定端口上只可以绑定一个容器
支持的格式如下:
-p <HostPort>:<ContainerPort>:映射至指定的主机端口 #常用
-p :<ContainerPort> 将制定的容器端口映射至主机所有地址的一个动态端口
-p <IP>::<ContainerPort>:映射至指定的主机的 IP 的动态端口
-p <IP>:<HostPort>:<ContainerPort>:映射至指定的主机 IP 的主机端口
查看端口的映射关系
docker port 容器ID|名字
例子:
[root@ds ~]# docker run -d --name tomcattest -P tomcat
[root@ds ~]# docker run -d --name tomcattest tomcat
[root@ds ~]# docker run -d --name tomcattest -p 8080:8080 tomcat
[root@ds ~]# docker port tomcattest1
8080/tcp -> 0.0.0.0:49155 #这个是使用-P 映射出来的随机端口
[root@ds ~]# docker port tomcattest2
[root@ds ~]# docker port tomcattest3
8080/tcp -> 0.0.0.0:8080 #这个是使用 -p指定的端口
4) 修改docker0 的参数
修改 /etc/docker/daemon.json 文件
{
"bip": "192.168.1.5/24",
"fixed-cidr": "10.20.0.0/16",
"fixed-cidr-v6": "2001:db8::/64", "mtu": "1500",
"default-gateway": "10.20.1.1",
"default-gateway-v6": "2001:db8:abcd::89", "dns": ["10.20.1.2","10.20.1.3"]
}
3.容器通信
需求 我们使用docker 0 的话 每次重启容器给容器分配的Ip都不一样 想让两个容器直接一直重启之后 也能保持通讯 ?
1) —link (不推荐使用 推荐使用自定义网络)
启动两个容器 tomcat1 tomcat 2
直接使用tomcat ping tomcat2 不使用ip 直接使用容器名字
[root@kuangshen ~]# docker exec -it tomcat02 ping tomcat01
#发现ping 不通
#我们在启动一个tomcat3 启动的时候使用--link 建立连接
docker run -d -P --name tomcat03 --link tomcat02 tomcat
#这个时候 我们就可以使用tomcat03 ping 通过tomcat02 了
[root@localhost ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.107 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.049 ms
^C
--- tomcat02 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.049/0.078/0.107/0.029 ms
#再来测试 tomcat03 能不能Ping同 tomcat01
[root@localhost ~]# docker exec -it tomcat03 ping tomcat01
ping: tomcat01: Name or service not known #没ping通
#我们试试2能不能Ping通3
[root@localhost ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat01: Name or service not known #没ping通
思考:这是什么原理呢????
#我们进入tomcat03 的hosts文件中
[root@localhost ~]# docker exec -it tomcat02 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.17.0.3 dfb518809337
#注意这里 tomcat2 的地址已经被写死在这里也就是添加了DNS
#--Link 已经过时了我们不推荐使用我们一般使用自定义网络的方式
2)自定义网络
# 默认我们不配置网络,也就相当于默认值 --net bridge 使用的docker0docker run -d -P --name tomcat01 --net bridge tomcat我们为什么使用自定义网络因为docker0 有缺点1.它是默认的2.不能使用域名访问3. --link 域名通了 但是容器删了又不行了
几种网络模式
| ** | ** | ** |
|---|---|---|
| bridge模式 | —net=bridge |
默认值,在Docker网桥docker0上为容器创建新的网络栈 |
| none模式 | —net=none | 不配置网络,用户可以稍后进入容器,自行配置 |
container 模式 |
— net=container:name/id |
容器和另外一个容器共享Network namespace。kubernetes中的pod就是多个容器共享一个Network namespace。 |
| host模式 | —net=host | 容器和宿主机共享Network namespace |
| 用户自定义 | —net=自定义网络 | 用户自己使用network相关命令定义网络,创建容器的时候可以指定为自己定义的网络 |
[root@localhost ~]# docker network --help #查看命令的参数
Usage: docker network COMMAND
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
docker network ls # 查看当前可用的网络类型
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
d2f390e4896e bridge bridge local
562bfa260e91 host host local
6dc802cb625e none null local
[root@localhost ~]# docker network create -d 类型 网络空间名称
# 创建自己的网络空间
类型分为:
overlay network #覆盖性网络 不同主机之间的docker实现通讯
bridge network #使用网桥 (我们是使用这个)
想知道更多的 使用命令 docker network create --help
我们创建一个自定义网络
--subnet 192.168.0.0/16 这个是网段 这个网段能分配的可用Ip数量为255*255-2
--gateway 192.168.0.1 这个是网关地址
--driver bridge 网络类型为brigde
这些参数 docker network create --help 里边都有
[root@kuangshen ~]# docker network create --driver bridge
--subnet 192.168.0.0/16
--gateway 192.168.0.1 mynet
09bd09d8d3a6b33e6d19f49643dab551e5a45818baf4d5328aa7320c6dcfc236
查看 
确认一下 使用这个命令 可以查看详细信息
[root@localhost ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "5419db07421520f6955befe69956b3ce6c8de26bc28f264922b3ccdeb91bac4d",
"Created": "2021-05-07T03:30:27.390633497+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
......
3)实验:
自己运行两个容器 把这两个融入到我们自定义的网络空间
1.运行镜像 把他们都放在 我们自己创建的网络空间中
[root@localhost ~]# docker run --name tomcat-net-01 -P -d --net mynet tomcat
a9a9807ea341235656cf280bacad96a1ff7f006e6758290ec44b1a7257995105
[root@localhost ~]# docker run --name tomcat-net-02 -P -d --net mynet tomcat
891f54622b6a7e07feb3409b3978b95cd67d56a5335e2795816601411c6c4397
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
891f54622b6a tomcat "catalina.sh run" About a minute ago Up About a minute 0.0.0.0:49156->8080/tcp, :::49156->8080/tcp tomcat-net-02
a9a9807ea341 tomcat "catalina.sh run" About a minute ago Up About a minute 0.0.0.0:49155->8080/tcp, :::49155->8080/tcp tomcat-net-01
[root@localhost ~]#
#查看下 docker network inspect mynet
[root@localhost ~]# docker network inspect mynet
.....
"ConfigOnly": false,
"Containers": {
"891f54622b6a7e07feb3409b3978b95cd67d56a5335e2795816601411c6c4397": {
"Name": "tomcat-net-02",
"EndpointID": "e3440b1d8adf4c901c04fd89369e523c63c0d212350cda5116b1c5b3685d34ba",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}, #注意看这里 这两个就是我我们刚才加入的容器 才这里就可以看到
"a9a9807ea341235656cf280bacad96a1ff7f006e6758290ec44b1a7257995105": {
"Name": "tomcat-net-01",
"EndpointID": "2dc108f285ea6b3641b268e0e569666c7a9401a133e8d776468f2d782c1408c4",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
......
#测试:ping 容器名和ip 是否能ping通
[root@localhost ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
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.108 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.081 ms
[root@localhost ~]# docker exec -it tomcat-net-02 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.070 ms
[root@localhost ~]# docker exec -it tomcat-net-02 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.095 ms
自定义网络 比docker 0 方便的地方就在这里 ping 容器名 和 Ip 都能ping 通过
网络联通实验
需求: 怎么让tomcat01 能访问到 tomcat-net-01
1.解决办法1
我们来查一下 network 的帮助找到一个解决办法
[root@localhost ~]# docker network --help
Usage: docker network COMMAND
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
#命令 docker network connect [OPTIONS] NETWORK CONTAINER
使用 docker network connect mynet tomcat01
查看一下 docker network inspect mynet
这样他们就可以相互ping 通了
2.解决办法2
原理 使用一张网卡来做一个容器的网络空间 让他可以在公网上被访问到
然后另一张网卡使用的是docker0 以nat 的方式来访问 公网上的 另一个容器
1.修改网卡配置文件
注意两张网卡都要该
改完之后 ens33 是没有ip 地址的 br 0 有Ip地址 要注意
我在这里困了好久 困了2小时 就是因为这个 我傻逼了
[root@localhost network-scripts]# vi ifcfg-eth0
DEVICE=eth0 HWADDR=00:0C:29:06:A2:35
TYPE=Ethernet
UUID=34b706cc-aa46-4be3-91fc-d1f48c301f23 ONBOOT=yes
BRIDGE=br0
NM_CONTROLLED=yes
BOOTPROTO=static
[root@localhost network-scripts]# vi ifcfg-br0
//改成这样DEVICE=br0
TYPE=Bridge
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.216.131
ETMASK=255.255.255.0
GATEWAY=192.168.216.2
DNS=8.8.8.8
重启网卡
systemctl restart network
2. 把这张网卡 当作新容器的网络空间
我们需要借助一个东西
一个叫做 pipework 的东西 来把我们准备好的网络空间来
赋予给这个容器
yum install -y git
git clone https://github.com/jpetazzo/pipework
cp pipework/pipework /usr/local/bin/ #前边是下载这个命令的
chmod 700 /usr/local/bin/pipework #防止没有执行权限
docker run --net=none --name=ds tomcat:v1.0
pipework br0 ds 192.168.88.99/24
当然这个命令不是 永久生效的 就是临时生效 我们要写入
开机 自动执行的配置文件中
网络空间分类 图表

