文章目录
-
- [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运作的基本流程是:
- 用户是使用Docker Client与Docker Daemon建立通信,并发送请求给后者
- Docker Daemon作为Docker架构的主体部分,首先提供Docker Server的功能使其可以接受Docker Client的请求
- Docker Engine执行Docker内部的一系列工作,每一项工作都是以一个job的形式存在
- Job的运行流程中,当需要容器镜像的时候,则从Docker Registry中下载镜像,并通过镜像管理驱动Graph Driver将下载镜像以Graph的形式存储
- 当需要为Docker创建网络环境时,通过网路管理器驱动NetWork driver创建并配置Docker容器网络环境
- 当需要限制Docker容器运行资源或执行用户命令的时候,则通过Execdriver来完成
- 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通了