Docker高级篇之Docker网络

文章目录

    • [1. Docker Network简介](#1. Docker Network简介)
    • [2. Docker 网络模式](#2. Docker 网络模式)
    • [3. Docker 网络模式之bridge](#3. Docker 网络模式之bridge)
    • [4. Docker 网络模式之host](#4. Docker 网络模式之host)
    • [5. Docker 网络模式之none](#5. Docker 网络模式之none)
    • [6. Docker 网络模式之container](#6. Docker 网络模式之container)
    • [7. Docker 网络模式之自定义网络模式](#7. Docker 网络模式之自定义网络模式)

1. Docker Network简介

从Docker的架构和运作流程来看,Docker是一个C/S模式的架构,后端是一个松耦合架构,众多模块各司其职。Docker运作的基本流程是:

  1. 用户是使用Docker Client与Docker Daemon建立通信,并发送请求给后者
  2. Docker Daemon作为Docker架构的主体部分,首先提供Docker Server的功能使其可以接受Docker Client的请求
  3. Docker Engine执行Docker内部的一系列工作,每一项工作都是以一个job的形式存在
  4. Job的运行流程中,当需要容器镜像的时候,则从Docker Registry中下载镜像,并通过镜像管理驱动Graph Driver将下载镜像以Graph的形式存储
  5. 当需要为Docker创建网络环境时,通过网路管理器驱动NetWork driver创建并配置Docker容器网络环境
  6. 当需要限制Docker容器运行资源或执行用户命令的时候,则通过Execdriver来完成
  7. Libcontainer是一项独立的容器管理包,NetWork driver以及Exec driver都是通过Libcontainer来实现具体对容器进行的操作

我们可以使用下面的命令来查看docker的所有网络情况:

bash 复制代码
docker network ls

bridge host 和 none是Docker 默认创建的

使用下面命令可以创建一个docker network:

bash 复制代码
docker network create test_network

使用下面命令可以删除一个docker网络:

bash 复制代码
docker network rm test_network

使用下面命令可以查看某个网络的详细信息:

bash 复制代码
docker network inspect bridge

Docker网络主要是实现两个功能:

  • 容器间的互联和同学以及端口映射
  • 容器IP变动时可以通过服务名直接网络通信而不受到影响

2. Docker 网络模式

签名说到Docker会默认给我们创建bridge、host和none三个网络模式。Docker常见的网络模式如下所示:

网络模式 简介 使用方式
bridge 为每一个容器分配、设置IP,并将容器链接到一个docker0,虚拟网桥,docker默认为该模式 --network bridge指定,默认是docker 0
host 容器将不会虚拟出自己的网卡,配置自己的IP地址,而是使用宿主机的IP和端口 使用--network host指定
none 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair和网桥连接,IP等 使用--network none指定
container 新建立的容器不会创建自己的网卡和配置自己的IP,而是和一个指定的容器共享IP、端口范围等 使用--network container:Name或者容器ID指定
  • docker netwrok底层ip和容器映射关系变化

我们启动两个ubuntu容器并进入ubuntu的容器内:

bash 复制代码
docker run -it --name u1 ubuntu bash
docker run -it --name u2 ubuntu bash

我们首先看一下u1的情况:

bash 复制代码
docker inspect u1

我们再看看u2:

可以发现u1和u2的网络ip都不一样。现在将u2删除,然后再启动一个u3,再次查看网络情况:

我们可以发现u3复用来u2的ip地址,这里就出现一个关键问题,如果我们在bridege情况下将容器ip写死的话,如果某个容器宕机了,它的ip地址可能被其它容器复用,这样就导致了访问u2的ip地址,可能访问到的是u3的内容,所以在访问容器服务时,不能通过固定的ip地址访问。所以我们要规划好我们的docker network

3. Docker 网络模式之bridge

Docker服务默认会创建一个docker0网桥(其上有一个docker0内部接口),该桥接网络的名称为docker 0,它在内核层连通了其他的物理或虚拟网卡,这就是将容器和本地主机都放在同一个物理网络,Docker默认指定了docker0接口的IP地址和子网掩码,让主机和容器之间可以通过网桥相互通信。

在组网方面,网桥网络是一种链路层设备,用于转发网段之间的流量。网桥可以是在主机内核中运行的硬件设备或软件设备。在Docker方面,网桥网络使用软件网桥,允许连接到同一网桥网络的容器进行通信,同时提供与未连接到该网桥网络的容器的隔离。Docker Bridge驱动程序自动在主机中安装规则,使不同网桥网络上的容器无法直接通信。网桥网络适用于运行在同一个Docker守护进程主机上的容器。对于运行在不同Docker守护进程主机上的容器之间的通信,可以在操作系统级别管理路由,也可以使用覆盖网络。启动Docker时,将自动创建默认网桥网络(也称为网桥),除非另有指定,否则新启动的容器将连接到该网络。还可以创建用户定义的自定义网桥网络。用户定义的网桥网络优于默认的网桥网络。

Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥,Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一个宿主机内的容器都接入同一个网桥,这样容器之间就能通过容器的Container-IP进行通信了。在执行docker run命令时,没有指定network的话默认使用的网桥模式就是bridge,使用的就是docker0。在宿主机上使用ifconfig,就可以看到docker0和自己create的network eth0、eth1、eth2,代表网卡1、网卡2...,lo代表127.0.0.1,即localhost,inet addr用来表示网卡的IP地址。

网桥docker0创建一对对虚拟设备接口叫做veth,另一个叫eth0,成对匹配:

  • 整个宿主机的网桥模式都是docker0,类似交换机有一个接口,每个接口叫做veth,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫做veth pair)
  • 每个容器实例内部也有一张网卡,每个接口就走eth0
  • docker0上面的每个veth匹配某个容器实例内部的eth0,两两配对,一一匹配

所以,将宿主机上的所有容器都链接到这个内部网络上,两个容器在同一个网络下,就从这个网关下各自拿到分配的ip,此时两个容器的网络是互通的。

4. Docker 网络模式之host

host模式是直接使用宿主机的ip地址与外界进行通信,不需要额外进行NAT转换。

NAT(Network Address Translation)是一种网络技术,用于在本地网络中使用私有地址,在连接互联网时转而使用全局IP地址。NAT技术主要解决了IPv4地址短缺的问题,通过将一个外部IP地址和端口映射到更大的内部IP地址集来实现IP地址的转换。NAT的实现方式包括静态转换、动态转换和端口多路复用(PAT)。

在host模式下,容器将不会获取一个独立的Network Namespace,而是和宿主机共用一个Network Namespace,容器将不会虚拟出自己的网卡而是使用宿主机的IP和端口。

我们举一个简单的例子:

bash 复制代码
docker run -d -p 8081:8080 --network host --name tomcat81 64fbf6b1021d

我们可以发现在host模式下,端口是空的,这是因为此时容器和主机是共用ip和端口的,所以host模式下端口会失效,端口会以主机端口号为主,重复时则递增

bash 复制代码
docker inspect tomcat81

由于和宿主机共用,所以很多配置都是空的,我们进入容器内部看网络配置,可以发现内容就是宿主机的网络配置情况

现在的问题时,因为-p端口失效,如何访问启动好的tomcat呢?(会使用tomcat默认的端口)

5. Docker 网络模式之none

在这种模式下,docker容器会禁用网络功能,只有lo标识(就是127.0.0.1表示本地回环)。在none模式下,并不为docker容器进行任何网络配置,也就是说,这个Docker容器没有网卡、IP、路由等信息,只有一个lo。需要我们自己为Docker容器添加网卡、配置IP等。

6. Docker 网络模式之container

新建的容器和已经存在的容器共享一个网络ip配置,而是不和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的文件系统、进程列表都是隔离的。

这里我们使用Alpine操作系统(Alpine时一个面向安全的Linux发行版)来演示:

bash 复制代码
docker run -it --name alpine1 alpine /bin/sh
docker run -it --network container:alpine1 --name alpine2 alpine /bin/sh

我们首先查看alpine1的网络情况:

再查看alpine2的网络情况:

可以看到alpine2的网卡情况和alpine1完全一致,所以alpine2确实复用了alpine1的网络(alpine1如果关闭了alpine2就会失去访问网络的功能)。

7. Docker 网络模式之自定义网络模式

前面说到Docker默认使用bridge模式,所有的容器都可以互通,如果我们现在的需求时某些业务相关的容器可以互通,而其它容器不能和这些容器通信,这时就需要使用到自定义的网络模式。

下面结合案例理解一下如何使用这种网络模式:

新建立两个tomcat容器:

bash 复制代码
docker run -d -p 8081:8080  --name tomcat81 64fbf6b1021d
docker run -d -p 8082:8080  --name tomcat82 64fbf6b1021d

此时默认使用bridge模式

现在我们分别进入两个容器内部:

然后我们看看根据ip地址是不是两个tomcat容器可以ping通。

tomcat81的ip地址:172.17.0.2

tomcat82的ip地址:172.17.0.3

可以发现时可以互相ping通的,但是如果现在安装服务名(tomcat81和tomcat82)就ping不通了

现在我们来使用我们的自定义网络:

首先新建立一个网络:

bash 复制代码
docker network create jackiechai_network

将tomcat容器加入到这个网络中:

bash 复制代码
docker run -d -p 8081:8080 --network jackiechai_network  --name tomcat81 64fbf6b1021d
docker run -d -p 8082:8080 --network jackiechai_network  --name tomcat82 64fbf6b1021d

现在再两个容器内部就可以安装ip或者具体的服务名来ping通了

相关推荐
涔溪27 分钟前
HTTP TCP三次握手深入解析
网络·tcp/ip·http
憨子周27 分钟前
2M的带宽怎么怎么设置tcp滑动窗口以及连接池
java·网络·网络协议·tcp/ip
网络研究院1 小时前
Am I Isolated:一款安全态势基准测试工具
容器·工具·基准测试·安全态势
三菱-Liu1 小时前
三菱MR-J4-B伺服连接器和信号排列
网络·驱动开发·硬件工程·制造·mr
WeeJot嵌入式1 小时前
网络安全:挑战、策略与未来趋势
网络
涔溪2 小时前
Docker简介
spring cloud·docker·eureka
内核程序员kevin3 小时前
在Linux环境下使用Docker打包和发布.NET程序并配合MySQL部署
linux·mysql·docker·.net
kayotin4 小时前
Wordpress博客配置2024
linux·mysql·docker
a1denzzz5 小时前
Linux系统的网络设置
linux·服务器·网络
颜淡慕潇5 小时前
【K8S问题系列 | 9】如何监控集群CPU使用率并设置告警?
后端·云原生·容器·kubernetes·问题解决