Docker-09-网络原理

Docker-09-网络原理

前言

当你开始大规模使用Docker时,你会发现需要了解很多关于网络的知识。Docker作为目前最火的轻量级容器技术,有很多令人称道的功能,如Docker的镜像管理。然而,Docker同样有着很多不完善的地方,网络方面就是Docker比较薄弱的部分。因此,我们有必要深入了解Docker的网络知识,以满足更高的网络需求。本文首先介绍了Docker自身的4种网络工作方式,然后介绍一些自定义网络模式。

1. 理解 Docker 0

  • 首先通过ip addr 查看ip环境

mark

可以明显的看到网络有三个地址。

我们每启动一个docker 容器,docker就会给docker容器分配一个ip ,我们只要安装了docker ,就会有一个docker网卡docker0

  • 使用的技术是evth-pair技术!(桥接模式)

    • 在主机上创建一对虚拟网卡veth pair设备。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备
  • Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0。另一端放在主机中,以veth65f9这样类似的名字命名,并将这个网络设备加入到docker0网桥中,可以通过brctl show命令查看。

    • 从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。
  • 每启动一个容器,就会多一对网络地址

  • 所以docker容器之间都是可以互相ping通的!!!

示意图:

mark

结论:

  • 所有的容器不指定网络的情况下,都是由docker0路由的,docker会给每一个容器分配一个可用的Ip
  • Docker中的所有网络都是虚拟的,这样转发的效率高。
  • 只要容器删除,对应的网桥就没了。

接下来有个思考问题?

  • 如果宕机(或者重启),容器ip发生了变化,那么可以使用名字来访问容器吗?

# 如: 通过--link就可以解决

1
2
3
4
5
6
7
docker run -d -P --name 服务名1 --link 服务名2 要启动的服务

# 如: 通过--link就可以解决
docker run -d -P --name tomcat01 --link tomcat02 tomcat

注意:
这样只能实现单向的联通
  • -- link : 本质上就是在etc/hosts 中增加了另一个服务的映射

  • 但是-- link 已经不推荐使用(Docker0 不支持容器名访问)

3. 自定义网络

3.1 网络模式

安装Docker时,它会自动创建三个网络,bridge(创建容器默认连接到此网络)、 none 、host

网络模式 简介
Host 容器不会虚拟自己的网卡,配置自己的Ip地址,而是使用宿主机的ip和端口
Bridge 此模式会为了每一个容器分配,设置IP,并将容器连接到一个docker0的虚拟网桥,通过docker0网桥连接以及iptables nat表配置与宿主机的通信
none 该模式关闭了容器的网络功能
Container 创建的容器不会创建自己的网卡,配置自己的ip,而是和一个指定的容器共享ip,端口范围
自定义网络

3.2 默认网络

1
2
3
4
5
[root@server1 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
0147b8d16c64 bridge bridge local
2da931af3f0b host host local
63d31338bcd9 none null local

mark

  • Docker内置这三个网络,运行容器时,你可以使用该–network标志来指定容器应连接到哪些网络。

  • 该bridge网络代表docker0 所有Docker安装中存在的网络。除非你使用该docker run –network=选项指定,否则Docker守护程序默认使用Bridge模式

3.3 自定义网络

  • 建议使用自定义网桥来控制哪些容器之间可以相互通信,还可以自动DNS解析容器名称到ip地址
  • Docker提供了创建这些网络的默认网络驱动程序,你可以创建一个新的Bridge网络,Overlay或Macvlan网络

接下来介绍Dokcer的内置网络驱动程序。

  1. Bridge
1
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
  • 一个bridge网络是Docker中最常用的网络类型。
  • 桥接网络类似于默认bridge网络,但添加一些新功能并删除一些旧的能力。

创建成功后结果如下:

1
2
3
4
5
6
root@Zhuuu:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
38cf4307d18e bridge bridge local
227d5be3657a host host local
b1ae1f4f0884 mynet bridge local
84aeff069277 none null local
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
root@Zhuuu:~# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "b1ae1f4f088456d79d05194b76b69a2ecc543249bc061f5dca8cccf88cf0dd18",
"Created": "2020-06-04T14:50:29.74809742+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": {}
}
]

测试:创建两个tomcat容器并丢入我们自己创建的网络

1
2
3
4
root@Zhuuu:~# docker run -d -P --name tomcat-net-01 --net mynet tomcat
9e43abf5054091f38d76ccd85c1b7324f266920ef31576d33293faf3281c2b34
root@Zhuuu:~# docker run -d -P --name tomcat-net-02 --net mynet tomcat
1ce722ed205dc443ec308665e0bffd5d9e2c148d65728c278b2f5e5aa13ac9b0

再次查看:发现多出了两个容器在这个网络中

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@Zhuuu:~# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "b1ae1f4f088456d79d05194b76b69a2ecc543249bc061f5dca8cccf88cf0dd18",
"Created": "2020-06-04T14:50:29.74809742+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": {
"1ce722ed205dc443ec308665e0bffd5d9e2c148d65728c278b2f5e5aa13ac9b0": {
"Name": "tomcat-net-02",
"EndpointID": "dc2f31d7e5955a2d43945b30b16f70bc017a7eb60fc5556c27ca76b579c96d6e",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"9e43abf5054091f38d76ccd85c1b7324f266920ef31576d33293faf3281c2b34": {
"Name": "tomcat-net-01",
"EndpointID": "b18174355605a296f99d10182219e41d746da84cab390d5682f3c870e598bc4d",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
  • 优点:
    • 不使用 – link 也可以让容器通过网桥互通
    • 自定义的网络已经维护好了对应的关系
    • 推荐使用自定义网络
    • 不同集群之间网络是可以互相隔离的
1
2
3
4
5
root@Zhuuu:~# 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.125 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.093 ms
^Z64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.106 ms

3.4 自定义网络连通

mark

1
2
# 命令使用
docker network connect 网卡 容器名

测试

  1. 在docker0上新建两个tomcat容器
1
2
root@Zhuuu:~# docker run -d -P --name tomcat01 tomcat
root@Zhuuu:~# docker run -d -P --name tomcat02 tomcat
  1. 目前网络图

mark

  1. 打通网络(tomcat02 加入到 mynet中)
1
docker network connect  mynet tomcat02

结果:将tomcat02加入到了mynet网络中(一个容器,两个ip)

1
2
3
4
5
6
root@Zhuuu:~# docker network connect mynet tomcat02
root@Zhuuu:~# docker exec -it tomcat02 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.092 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.079 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.094 ms

mark

4. 网络实战

4.1 部署redis集群

  • 分片 + 高可用 + 负载均衡
  1. 创建集群网络环境
1
docker network create redis --subnet 172.38.0.0/16

mark

  1. 创建6个redis服务并修改配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
  1. 启动6个服务
1
2
3
4
5
6
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.0${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf; \

# ${port}就代表自身的端口号
  1. 进入redis配置集群
1
2
3
4
5
# 进入redis配置集群
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

4.2 SpringBoot 微服务打包Docker镜像

  1. 构建SpringBoot 项目
1
2
3
4
5
6
7
8
@RestController
public class HelloController {

@RequestMapping("/hello")
public String hello(){
return "hello,朱酱酱";
}
}
  1. 打包应用

mark

  1. 编写dockerfile
  • 在idea中装一个插件

mark

安装成功之后:

mark

  • 编写dockerfile
1
2
3
4
5
6
7
8
9
FROM java:8

COPY *.jar /app.jar

CMD ["--server.port=8080"]

EXPOSE 8080

ENTRYPOINT ["java","-jar","/app.jar"]
  1. 发布运行
  • 只需要把生成的jar包和dockerfile放到服务器上即可

mark

  • 服务端构建镜像
1
docker build -t zhuuu666 .

mark

  • 最后启动测试
1
docker run -d -P --name testproject-web zhuuu666

mark

搞定收工!!!

打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2019-2022 Zhuuu
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信