【Docker学习笔记 七】深入理解Docker网络配置及微服务部署(上)

简介: 【Docker学习笔记 七】深入理解Docker网络配置及微服务部署(上)

由于Docker在工作中大多数场景用不到,对于一个后端开发者而言,仅仅从使用上和原理上了解一下即可,所以网络配置是Docker学习笔记基础篇的最后一篇,后续一段时间的精力可能会投入到《设计模式》上去,至于Docker更高级的用法,涉及Docker Compose容器编排、Docker Swarm集群部署、CICD/Jenkins以及Kubernates等内容后续有精力有时间或者成为工作痛点的时候再花时间了解。

Docker再安装

因为网络部分内容比较复杂,为了效果更明显些,不受历史内容影响,我决定换个宿主机操作,毕竟咱有三个虚拟机,召唤TML-2即可。还是按照之前学习的安装方式:

详细步骤就不重复之前的了,感兴趣可以参考我专栏的这篇Blog:【Docker学习笔记 二】Docker安装、运行流程与常用命令, 经过一系列命令操作可以看到我已经在第二台虚拟机上安装了Docker:

[root@192 ~]# docker version
Client: Docker Engine - Community
 Version:           20.10.12
 API version:       1.41
 Go version:        go1.16.12
 Git commit:        e91ed57
 Built:             Mon Dec 13 11:45:41 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true
Server: Docker Engine - Community
 Engine:
  Version:          20.10.12
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.12
  Git commit:       459d0df
  Built:            Mon Dec 13 11:44:05 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.13
  GitCommit:        9cc61520f4cd876b86e77edfeb88fbcd536d1f9d
 runc:
  Version:          1.0.3
  GitCommit:        v1.0.3-0-gf46b6ba
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

并且配置好了阿里云的镜像加速。

Docker默认的网络模式

首先我们使用查看ip地址的命令ip addr查看下当前的网络地址有哪些:

[root@192 ~]# 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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:39:b4:c3 brd ff:ff:ff:ff:ff:ff
    inet 192.168.5.102/24 brd 192.168.5.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::f808:3fa:3eec:4af6/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:0b:48:4f brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:0b:48:4f brd ff:ff:ff:ff:ff:ff
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:c5:e1:d8:5b 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@192 ~]#

以上各个网络地址解释如下:

  • lo为本机环回地址,也就是我自己的windows主机
  • ens33是虚拟机TML-2的地址,也就是Docker的宿主机的网络地址192.168.5.102
  • virbr0 是 KVM 默认创建的一个 Bridge,其作用是为连接其上的虚机网卡提供 NAT 访问外网的功能。 virbr0 默认分配了一个IP 192.168.122.1,并为连接其上的其他虚拟网卡提供 DHCP 服务
  • virbr0-nic 代表虚拟网桥NIC。 它基本上是物理网卡和虚拟机的虚拟网卡之间的桥梁
  • docker0即是docker使用的网络地址

属实是三层套娃了。使用以下命令查看所有的Docker网络模式:

[root@192 ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
173795075c5b   bridge    bridge    local
fcddcee8a2d1   host      host      local
9efbda880fae   none      null      local
[root@192 ~]#

Docker默认提供了四个网络模式,说明:

  • bridge容器默认的网络是桥接模式(自己搭建的网络默认也是使用桥接模式,启动容器默认也是使用桥接模式)。此模式会为每一个容器分配、设置IP等,并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。
  • none不配置网络,容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等。
  • host:容器和宿主机共享Network namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口
  • container:创建的容器不会创建自己的网卡,配置自己的IP容器网络连通。容器和另外一个容器共享Network namespace(共享IP、端口范围)

容器默认使用bridge网络模式,我们使用该docker run --network=选项指定容器使用的网络:

host模式:使用 --net=host 指定。
none模式:使用 --net=none 指定。
bridge模式:使用 --net=bridge 指定,默认设置。
container模式:使用 --net=container:NAME_or_ID 指定

Namespace:Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。

1 host模式

如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好

2 container模式

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。

同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。

3 none模式

使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。

这种网络模式下容器只有lo环回网络,没有其他网卡。none模式可以在容器创建时通过–network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。

4 bridge模式

当Docker进程启动时,会在宿主机上创建一个名为docker0的虚拟网桥,宿主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。

从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。

bridge模式是docker的默认网络模式,不写–net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。

当Docker server启动时,会在宿主机上创建一个名为docker0的虚拟网桥,此宿主机启动的Docker容器会连接到这个虚拟网桥上。Docker0使用到的技术是evth-pair技术。在默认bridge网络模式下,我们每启动一个Docker容器,Docker就会给Docker容器配置一个ip。Docker容器完成bridge网络配置的过程如下:

  1. 在宿主机上创建一对虚拟网卡veth pair设备。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备。
  2. Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0。另一端放在主机中,以veth65f9这样类似的名字命名,并将这个网络设备加入到docker0网桥中。
  3. 从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。

网络请求到来时可以通过端口转发功能到达。我们来测试下这种默认模式,在上篇Blog中我们成功将一个自制的tomcat镜像推送到了DockerHub,那么本篇Blog我们就来使用自制的tomcat来操作下,梦幻联动一波:

下载镜像查看结果:

[root@192 ~]# docker run -d -P --name tomcat-tml tianmaolin/tml-mydockerfile-tomcat:1.0
Unable to find image 'tianmaolin/tml-mydockerfile-tomcat:1.0' locally
1.0: Pulling from tianmaolin/tml-mydockerfile-tomcat
2d473b07cdd5: Pull complete 
4adf06756b56: Pull complete 
25761eba323d: Pull complete 
30ccbd4f8175: Pull complete 
83bf41c456b8: Pull complete 
Digest: sha256:d829761d327aea380c934da8c58873843cfe0e1872d5cdb958afc2557b268db0
Status: Downloaded newer image for tianmaolin/tml-mydockerfile-tomcat:1.0
50b626fc91d2660232e9b299b09d65c232e33cb2ccfcbbc65307fbadf6eb91ef
[root@192 ~]# docker images
REPOSITORY                           TAG       IMAGE ID       CREATED      SIZE
tianmaolin/tml-mydockerfile-tomcat   1.0       94dbe2d0cb91   6 days ago   799MB
[root@192 ~]# docker ps
CONTAINER ID   IMAGE                                    COMMAND                  CREATED         STATUS              PORTS                                         NAMES
50b626fc91d2   tianmaolin/tml-mydockerfile-tomcat:1.0   "/bin/sh -c '/usr/lo…"   2 minutes ago   Up About a minute   0.0.0.0:49154->8080/tcp, :::49154->8080/tcp   tomcat-tml
[root@192 ~]#

访问测试如下:

然后进入容器查看容器网络设置:

[root@192 ~]# docker exec -it  50b626fc91d2 ip addr
OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "ip": executable file not found in $PATH: unknown
[root@192 ~]# docker exec -it  50b626fc91d2 /bin/bash

好吧,缺少网络配置,因为之前的tomcat是基于centos基础版本构建的,所有缺少网络工具,我还是使用最新版的集成版tomcat8:

[root@192 ~]# docker run -d -P --name tomcat01 tomcat:8.0
Unable to find image 'tomcat:8.0' locally
8.0: Pulling from library/tomcat
f189db1b88b3: Pull complete 
3d06cf2f1b5e: Pull complete 
edd0da9e3091: Pull complete 
eb7768aae14e: Pull complete 
e2780f585e0f: Pull complete 
e5ed720afeba: Pull complete 
d9e134700cfc: Pull complete 
e4804b33d02a: Pull complete 
b9df0c24315e: Pull complete 
49fdae8eaa20: Pull complete 
1aea3d9a32e6: Pull complete 
Digest: sha256:8ecb10948deb32c34aeadf7bf95d12a93fbd3527911fa629c1a3e7823b89ce6f
Status: Downloaded newer image for tomcat:8.0
WARNING: IPv4 forwarding is disabled. Networking will not work.
6cd417097796215ffdb1563bb71ba2c500b8e91adb4049880fc0d7f1b366def9
[root@192 ~]# 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
10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@192 ~]#

可以看到容器启动后Docker分配给容器一个格式如eth0@if11 的ip地址。宿主机运行ip addr命令查看变化:

[root@192 ~]# 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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:39:b4:c3 brd ff:ff:ff:ff:ff:ff
    inet 192.168.5.102/24 brd 192.168.5.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::f808:3fa:3eec:4af6/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:0b:48:4f brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
       valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:0b:48:4f brd ff:ff:ff:ff:ff:ff
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:c5:e1:d8:5b 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
    inet6 fe80::42:c5ff:fee1:d85b/64 scope link 
       valid_lft forever preferred_lft forever
9: vethd4ac7ba@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 9e:dd:50:f2:d3:ae brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::9cdd:50ff:fef2:d3ae/64 scope link 
       valid_lft forever preferred_lft forever
11: veth1f00e42@if10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 9e:71:e9:ab:e6:8e brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::9c71:e9ff:feab:e68e/64 scope link 
       valid_lft forever preferred_lft forever
[root@192 ~]#

可以看到宿主机多了两个网卡,其中veth1f00e42@if10和tomcat01的网卡相对,vethd4ac7ba@if8就是和我自制镜像生成的容器tomcat-tml相对,而这两个网卡都是成对的。使用的技术就是evth-pair。evth-pair 就是一对的虚拟设备接口,他们是成对出现的,一段连着协议,一段彼此相连。evth-pair充当一个桥梁,连接各种虚拟网络设备。执行iptables -t nat -vnL命令查看一下

[root@192 ~]# iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 1 packets, 229 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   10   520 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL
Chain INPUT (policy ACCEPT 1 packets, 229 bytes)
 pkts bytes target     prot opt in     out     source               destination         
Chain OUTPUT (policy ACCEPT 32 packets, 2368 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DOCKER     all  --  *      *       0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL
Chain POSTROUTING (policy ACCEPT 32 packets, 2368 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 MASQUERADE  all  --  *      !docker0  172.17.0.0/16        0.0.0.0/0           
    3   303 RETURN     all  --  *      *       192.168.122.0/24     224.0.0.0/24        
    0     0 RETURN     all  --  *      *       192.168.122.0/24     255.255.255.255     
    0     0 MASQUERADE  tcp  --  *      *       192.168.122.0/24    !192.168.122.0/24     masq ports: 1024-65535
    0     0 MASQUERADE  udp  --  *      *       192.168.122.0/24    !192.168.122.0/24     masq ports: 1024-65535
    0     0 MASQUERADE  all  --  *      *       192.168.122.0/24    !192.168.122.0/24    
    0     0 MASQUERADE  tcp  --  *      *       172.17.0.3           172.17.0.3           tcp dpt:8080
    0     0 MASQUERADE  tcp  --  *      *       172.17.0.2           172.17.0.2           tcp dpt:8080
Chain DOCKER (2 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0           
    6   312 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:49154 to:172.17.0.3:8080
    0     0 DNAT       tcp  --  !docker0 *       0.0.0.0/0            0.0.0.0/0            tcp dpt:49155 to:172.17.0.2:8080
[root@192 ~]#

可以看到DNAT的端口映射技术。尝试从宿主机 ping tomcat01容器:

[root@192 ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.095 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.055 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.068 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.039 ms
64 bytes from 172.17.0.2: icmp_seq=5 ttl=64 time=0.043 ms
64 bytes from 172.17.0.2: icmp_seq=6 ttl=64 time=0.099 ms
64 bytes from 172.17.0.2: icmp_seq=7 ttl=64 time=0.043 ms
64 bytes from 172.17.0.2: icmp_seq=8 ttl=64 time=0.044 ms
64 bytes from 172.17.0.2: icmp_seq=9 ttl=64 time=0.039 ms


相关文章
|
1月前
|
运维 Kubernetes Docker
利用Docker和Kubernetes构建微服务架构
利用Docker和Kubernetes构建微服务架构
|
17天前
|
关系型数据库 MySQL Docker
《docker高级篇(大厂进阶):5.Docker-compose容器编排》包括是什么能干嘛去哪下、Compose核心概念、Compose使用三个步骤、Compose常用命令、Compose编排微服务
《docker高级篇(大厂进阶):5.Docker-compose容器编排》包括是什么能干嘛去哪下、Compose核心概念、Compose使用三个步骤、Compose常用命令、Compose编排微服务
77 24
|
19天前
|
关系型数据库 MySQL Docker
《docker高级篇(大厂进阶):5.Docker-compose容器编排》包括是什么能干嘛去哪下、Compose核心概念、Compose使用三个步骤、Compose常用命令、Compose编排微服务
《docker高级篇(大厂进阶):5.Docker-compose容器编排》包括是什么能干嘛去哪下、Compose核心概念、Compose使用三个步骤、Compose常用命令、Compose编排微服务
98 6
|
1月前
|
监控 安全 持续交付
构建高效的微服务架构:从设计到部署
构建高效的微服务架构:从设计到部署
25 1
|
1月前
|
安全 持续交付 Docker
微服务架构和 Docker 容器化部署的优点是什么?
微服务架构和 Docker 容器化部署的优点是什么?
|
1月前
|
Docker 微服务 容器
使用Docker Compose实现微服务架构的快速部署
使用Docker Compose实现微服务架构的快速部署
68 1
|
2月前
|
安全 定位技术 数据安全/隐私保护
|
2月前
|
Kubernetes 负载均衡 Docker
构建高效微服务架构:Docker与Kubernetes的完美搭档
本文介绍了Docker和Kubernetes在构建高效微服务架构中的应用,涵盖基本概念、在微服务架构中的作用及其实现方法。通过具体实例,如用户服务、商品服务和订单服务,展示了如何利用Docker和Kubernetes实现服务的打包、部署、扩展及管理,确保微服务架构的稳定性和可靠性。
107 7
|
1月前
|
Kubernetes 负载均衡 Docker
构建高效微服务架构:Docker与Kubernetes的完美搭档
【10月更文挑战第22天】随着云计算和容器技术的快速发展,微服务架构逐渐成为现代企业级应用的首选架构。微服务架构将一个大型应用程序拆分为多个小型、独立的服务,每个服务负责完成一个特定的功能。这种架构具有灵活性、可扩展性和易于维护的特点。在构建微服务架构时,Docker和Kubernetes是两个不可或缺的工具,它们可以完美搭档,为微服务架构提供高效的支持。本文将从三个方面探讨Docker和Kubernetes在构建高效微服务架构中的应用:一是Docker和Kubernetes的基本概念;二是它们在微服务架构中的作用;三是通过实例讲解如何使用Docker和Kubernetes构建微服务架构。
68 6
|
2月前
|
Kubernetes 持续交付 Docker
探索DevOps实践:利用Docker与Kubernetes实现微服务架构的自动化部署
【10月更文挑战第18天】探索DevOps实践:利用Docker与Kubernetes实现微服务架构的自动化部署
109 2

热门文章

最新文章