6.docker的网络通讯

目录:

1. docker网络通讯的模式

2. docker网络模式的修改

3. 常见隔离方式


 

一. docker网络通讯的模式

docker 网络通讯的几种形式

1. 容器与容器之间

2. 容器访问外部网络

3. 外部网络访问容器

 

1.1 容器和容器之间如何进行通讯的?

 

1. 每台机器上都有一个网卡,有的甚至有两个网卡 , ETHD 10.1.1.10/8就表示一个网卡

2. docker启动以后, 会出现一个docker0,我们可以通过ifconfig来查看

 

 我们发现, 有一个docker0, docker0是什么?我们可以将其理解为交换机,术语称之为网桥, 那交换机有什么作用?交换不同容器之间的数据, 让数据间可以交流。

 交换机一旦创建以后, 就会创建一个叫namespace的东西,名字叫做network namespace. 全名叫做网络命名空间.也就是上图中蓝色方框VethX,不同的网络命名空间会形成相互隔离,一端固定在容器内容, 成为虚拟网卡, 另一端固定在本机。

进入到容器查看ip a,可以看到eth0的网卡

 

 在本机会生成一个类似vethe1abf09@if26的网卡与容器中的网卡相对应。

 

 只要多一个容器就会多一个veth。也就是说一端在容器里,另一端在本机里,作为连通的作用。 并且, 网络命名空间会将不同的网络隔离开来,各用个的。这样就实现了隔离,以及怎样与本机进行交互。这样,容器和容器之间就可以通讯了。  这解决的是容器和容器间进行通讯。 这是通过docker0网桥解决的

 

1.2. 容器如何访问外部网络

  iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -o docker0 -j MASQUERADE
  这是一个典型的SNAT转换, 这种方式是通过TNAT的方式实现的

  

1.3 外部网络如何访问容器 

   docker run -d -p 80:80 apache
   外部网络访问容器只需加上-p 80:80, 就会实现下面两个操作。
   iptables -t nat -A POSTROUTING -m addrtype --dst-type LOCAL -j DOCKER
   iptables -t nat -A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.2:80 

   这种方式是通过DNAT来实现的

 

二. 网络模式的修改

docker启动以后, 默认的网桥是docker0, 默认的ip地址172.0.0.1, 我们能不能修改默认的网桥和ip地址呢?接下来就看看有哪些值能被我们修改

1. docker进程网络修改参数

docker进程修改, 后面的容器都会跟着被修改. 相当于是主程序修改, 相应的容器都会跟着修改

  • -b, --bridge="" , 指定docker使用的网桥设备, 默认情况下docker启动的时候会自动创建并使用docker0网桥设备, 通过此参数,可以使用自定义的网桥设备

   也就是说, 我们的网桥是docker0, 如果你想要吧网桥改成docker1, 怎么改呢?设置一个参数--bridge="docker1"就可以了

  • --bip 指定docker0的ip和掩码,使用标准的CIDR形式, 如10.10.10.10/24. 其中24表示的就是子网掩码255.255.255.0. 这是一个默认的表达方式

  • --dns 配置容器的dns, 在启动docker进程的时候添加,所有容器都会生效

2. 容器网络的修改

--dns 用于指定启动的容器的DNS. 只在启动的容器生效
--net 用于指定容器的网络通讯方式, 有以下四个值  

  1. bridge: 网桥方式, 也是docker的默认方式. 也就是通过网桥进行数据通讯, 并且是隔离

  2. none: 没有任何的ip地址. 如果启动容器的时候, 使用了--net="none", 通过ip a查看容器的网络, 发现没有连接网络的信息. 也就是说不能和外界联通.

比如: 我们启动一个tomcat

docker run -it --name tomcat11 --net=none tomcat9 /bin/bash

 


我们在执行ip a查看网络情况. 我们发现没有外网连接.

一个容器,都不能上网了, 那还有什么用呢?

有些容器没必要有网络. 比如:有些容器是做计算的, 这种计算完把结果放在本地了,他不需要有网络,有了网络反而不安全了.只能自己跟自己通讯.
  

  3. container: 使用其他容器的网络栈,Docker容器会加入其他容器的network namespace. 如果使用同一个网络栈, 比如:一个容器是nginx,另一个容器是mysql. nginx就可以向在本地一样访问3306端口了. 这样安全性就差了, 但在有些环境, 就是要求要这种

  4. host: 表示容器使用host的网络, 没有自己独立的网络, 容器可以完全访问host的网络,
  我们启动一个tomcat:

 docker run --name tomcat11 --net=host -d tomcat:v1.0

  运行这个容器之前, 要确保本机的8080端口没有被使用

  然后在容器里运行curl http://locahost:8080

  

 

 

 

  再在虚拟机中运行curl http://localhost:8080

 

 

 

  我们发现,他们访问的内容是一样, 容器启动的时候没有使用-p 进行端口映射,为什么能访问呢?

  因为容器使用的host主机的网络, 相当于容器启动了8080端口, 默认主机也有这个端口, 所以可以直接访问.

 

3. 暴露端口

-p/-P 选项的使用

  • -p :<ContainerPort> 将制定的容器端口映射到主机所有地址的一个动态端口.

  • 意思是: 容器端口有了, 你要访问那个主机端口, 不确定, 这个是随机的
  • -p <HostPort>:<ContainerPort> 容器的指定端口映射到主机的指定端口 (最常用)
  • -p <IP>::<ContainerPort> 映射到指定的主机的IP的动态端口
  • -p <IP>:<HostPort>:<ContainerPort> 映射到指定主机ip的主机端口 (最常用)
  • -P , 暴露需要的所有端口

 

docker port 容器ID, 可以查看容器当前的端口映射关系

 

 

 

4. 自定义docker0网桥的网络地址

/etc/docker/daemon.json文件
{
'bip':"192.168.1.5/24"
"final-cidr":"10.20.0.0/36"
"default-gateway":"10.20.1.1"
"dns":["10.20.1.1", "10.20.1.3"]

}

 

三. 常见的隔离方式

我们先来看一种情况. 

我在192.168.198.142虚拟机上启动两个docker容器

docker run -it --name tomcat1 tomcat9 /bin/bash

docker run -it --name tomcat2 tomcat9 /bin/bash

查看两个容器的ip

 

 

 

 tomcat1的ip是172.17.0.2, tomcat2的ip是172.17.0.3.

那么我们在tomcat1中pingtomcat2的ip能不能ping通呢?

ping 172.17.0.3

 

 没问题, 我们看到, 确实是成功了. 这说明什么?

这说明, 如果容器1和容器2相互之间可以通过ip进行访问. 

那么,如果我不想让他们之间相互访问, 怎么办呢? 这就是容器和容器之间网络隔离

3.1 容器间网络隔离

所谓容器间网络隔离, 指的是容器和容器之间网络不通, 也就是ping不通.既然ping不通,那么相互之间就不能访问了. 但是依然是可以和主机相互访问的.

下面看几个命令:

docker network ls 

 

 

我们看到, 有一个网络是默认的bridge网络. 之所以上面两个tomcat容器之间可以相互访问, 原因是: 他们使用的是同一个网段. 如果我们想实现隔离, 让他们处于不同的网段就可以了.

我们可以通过下面的命令创建新的网段

docker network create -d 网络类型  网络名词
网络类型有两种
    overlay network---主要用在不同的主机中的容器可以互相通信,但是需要借助其他一些软件去实现
    bridge network---网桥.

下面我们就使用这种网桥来创建两个新的网络
docker network create -d bridge lamp

docker network create -d bridge lnmp

 

 查看当前已有的网络

 

 通过查看本机的ip,我们看到多了两个网络

 

 原来只有172.17.0.1网络, 现在增加了172.18.0.1/16 和 172.19.0.1/16

接下来,我们使用新的网络新建两个容器

 新建一个容器tomcat1, 设置他的网络使用lamp, 他的网段是172.18.0.1

docker run -it --name tomcat1 --network=lamp tomcat9 /bin/bash

进入到容器以后, 输入ip a查看容器的ip地址

 

 我们看到容器的ip地址是172.18.0.2

 

 

在新建一个容器2, 设置他的网络使用lnmp, 他的网段是172.19.0.1

 docker run -it --name tomcat2 --network=lnmp tomcat9 /bin/bash

进入到容器, 查看容器的ip

 

 我们看到容器2的ip地址是172.19.0.2

现在这两个容器处在不同的网段, 处于不同的两个网段, 他们之间肯定是ping不通的.

在容器1中ping 172.19.0.2, ping不通

 

反之, 在容器2ping容器1的ip也ping不通. 这样就实现了容器将网络的隔离

 

我们之前, 搭建的harbor仓库, 我们可以看一下这台服务的已经启动的docker网络

虚拟机:
192.168.198.143 查询docker网络命令 docker network ls

 

我们看到有一个名字叫做harbor_harbor的网络. 采用的network方式是bridge 

 

 3.2 如何让两台主机的两个容器之间可以通讯?

比如: 让ip是192.168.198.142虚拟机上的docker容器能够和192.168.198.143虚拟机上的docker容器进行通讯?

这里需要我们自己去指定网桥.

下面我们要搭建一个网桥, 这个网桥和外界具有真正的通讯能力. 什么叫真正的通讯能力呢? 

 相对而言, 指的是docker0这个网桥, docker0实际上是一个假的网桥. 他只能让本机的容器间具有通讯的能力. 却不能让不同主机之间的容器进行通讯.

 

我们现在要配置一个, 使用真正的物理网卡实现的网桥.  这个网桥能够跟外面的主机进行通讯. 

 

创建网桥有多种方法. 可以通过工具创建, 这里我们使用修改配置文件的方式创建网桥. 具体操作如下: 

 

第一步: 进入到/etc/sysconfig/network-scripts/
第二步: 拷贝ifcfg-ens33
       cp -a ifcfg-ens33 ifcfg-br0
第三步: 修改ifcfg-ens33
       删除ip的相关配置, 增加网桥配置BRIDGE=br0
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
#BOOTPROTO="dhcp"
BOOTPROTO="static"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_FAILURE_FATAL="no"
IPV6_ADDR_GEN_MODE="stable-privacy"
NAME="ens33"
UUID="1c73d826-0a58-4e97-8fd2-63ad33c4a5ad"
DEVICE="ens33"
ONBOOT="yes"
BRIDGE="br0"    // 增加BRIDGE

删除下面几项
IPADDR=192.168.198.142
NETMASK=255.255.255.0
GATEWAY=192.168.198.2
BROADCAST=192.168.198.255
DNS1=192.168.198.2
第四步: 修改ifcfg-br0
    删除全部配置, 重新添加以下内容. 注意重新设置ip
DEVICE=br0
TYPE=Bridge
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.198.142
NETMASK=255.255.255.0
GATEWAY=192.168.198.2
BROADCAST=192.168.198.255
DNS1=192.168.198.2
第五步: 重启网络
    systemctl network restart
第六步: 此时查看ip a
我们发现ens3的ip地址没有了, 多了一个br0的网桥

 

 

 

默认情况下,docker并不能介入到br0去通讯
我们可以使用pipework来打通docker容器和br0网络

下面, 设置pipework网络

 

1. 下载git  
   yum install -y git
2. git clone https://github.com/jpetazzo/pipework
3. cp pipework/pipework /usr/local/bin/
    chmod a+x /usr/local/bin/pipework
4. 启动容器, 设置--net为none
    docker run  --net=none --name tomcat -d tomcat9
    这里--net必须设置成none, 这样后面我们才能通过pipework给他设置一个独立的ip地址
 

 

 

 

5. 通过pipework赋予容器一个独立的ip地址 
  pipework 网桥类型  容器名称 ip地址
  pipework br0 tomcat 192.168.198.145/24

 

 

6. 验证网络

首先, 进入到容器, 查看容器的网络

 

 我们看到容器的网络确实设置为192.168.198.145

接下来, 接下来, 我在本机mac上ping刚刚设置的192.168.198.145.是可以ping通的

 

 然后在容器里, 虚拟机里, 本机macos上ping 192.168.198.145:8080都可以看到tomcat的启动页. 说明容器配置成功了

 

 

 这时容器也有自己独立的ip了.  我们在另一台虚拟机上192.168.198.143上ping 192.168.198.145, 我们发现也是可以ping通的了. 

 而且也可以访问http://192.168.198.145:8080 并且能够看到tomcat的启动页

 

 

 现在容器有了自己独立的ip, 可以和各种主机/容器进行通讯了.

 

posted @ 2020-06-11 06:48  盛开的太阳  阅读(485)  评论(0编辑  收藏  举报