【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


相关文章
|
11天前
|
运维 Kubernetes Cloud Native
云原生时代下,如何高效构建与部署微服务
【9月更文挑战第8天】随着云计算技术的飞速发展,云原生已成为现代软件架构的重要趋势。本文将深入浅出地介绍云原生概念、微服务架构的优势以及如何在云平台上高效构建和部署微服务。我们将通过实际的代码示例,展示在Kubernetes集群上部署一个简单的微服务应用的过程,帮助读者理解云原生环境下的微服务开发和运维实践。
|
17天前
|
Dubbo Java 应用服务中间件
微服务框架Dubbo环境部署实战
微服务框架Dubbo环境部署的实战指南,涵盖了Dubbo的概述、服务部署、以及Dubbo web管理页面的部署,旨在指导读者如何搭建和使用Dubbo框架。
68 17
微服务框架Dubbo环境部署实战
|
9天前
|
Docker Windows Python
Windows-Docker学习笔记(一)
本文介绍了Windows环境下Docker的安装与使用方法。首先通过链接下载Windows版本的Docker,然后按步骤配置:启用Windows功能、设置默认WSL版本为2,并检查Docker及其组件是否正常工作。接着详细列出了Docker的基础命令及其用法,包括搜索、下载镜像、管理容器等。同时介绍了Dockerfile的编写方法及其构建过程,以及docker-compose.yml文件的用途。最后提供了运行和管理容器的具体示例。
Windows-Docker学习笔记(一)
|
7天前
|
人工智能 API 数据库
FastGPT一站式解决方案[1-部署篇]:轻松实现RAG-智能问答系统(含sealos云端部署、docker部署、OneAPI&Xinference模型接入)
【9月更文挑战第5天】 FastGPT一站式解决方案[1-部署篇]:轻松实现RAG-智能问答系统(含sealos云端部署、docker部署、OneAPI&Xinference模型接入)
 FastGPT一站式解决方案[1-部署篇]:轻松实现RAG-智能问答系统(含sealos云端部署、docker部署、OneAPI&Xinference模型接入)
|
17天前
|
Docker 容器
Docker自建仓库之Harbor高可用部署实战篇
关于如何部署Harbor高可用性的实战教程,涵盖了从单机部署到镜像仓库同步的详细步骤。
57 15
Docker自建仓库之Harbor高可用部署实战篇
|
17天前
|
Shell Linux Docker
自定义Docker网络
这篇文章介绍了如何使用Docker命令自定义网络,并通过创建和配置网络来实现容器间的通信。
23 6
自定义Docker网络
|
1天前
|
负载均衡 网络协议 开发者
掌握 Docker 网络:构建复杂的容器通信
在 Docker 容器化环境中,容器间的通信至关重要。本文详细介绍了 Docker 网络的基本概念和类型,包括桥接网络、宿主网络、覆盖网络和 Macvlan 网络等,并提供了创建、管理和配置自定义网络的实用命令。通过掌握这些知识,开发者可以构建更健壮和灵活的容器化应用,提高应用的可扩展性和安全性。
|
17天前
|
NoSQL 关系型数据库 Redis
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
mall在linux环境下的部署(基于Docker容器),docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongodb、minio详细教程,拉取镜像、运行容器
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
|
17天前
|
虚拟化 Docker Windows
window 10专业版部署docker环境
本文介绍了如何在Windows 10专业版上部署Docker环境,包括安装步骤、配置镜像加速以及可能遇到的错误处理。
41 2
window 10专业版部署docker环境
|
17天前
|
NoSQL 应用服务中间件 Redis
Docker跨宿主机容器通信-通过网络跨宿主机互联
这篇文章介绍了Docker容器跨宿主机通信的实现方法,包括Docker的四种网络模式(host、none、container、bridge)以及如何通过修改网络配置和添加路由规则来实现不同宿主机上的容器之间的互联。
51 0
Docker跨宿主机容器通信-通过网络跨宿主机互联