docker 网络通讯的几种形式
1. 容器与容器之间
2. 容器访问外部网络
3. 外部网络访问容器
1. 每台机器上都有一个网卡,有的甚至有两个网卡 , ETHD 10.1.1.10/8就表示一个网卡
2. docker启动以后, 会出现一个docker0,我们可以通过ifconfig来查看
我们发现, 有一个docker0, docker0是什么?我们可以将其理解为交换机,术语称之为网桥, 那交换机有什么作用?交换不同容器之间的数据, 让数据间可以交流。
交换机一旦创建以后, 就会创建一个叫namespace的东西,名字叫做network namespace. 全名叫做网络命名空间.也就是上图中蓝色方框VethX,不同的网络命名空间会形成相互隔离,一端固定在容器内容, 成为虚拟网卡, 另一端固定在本机。
进入到容器查看ip a,可以看到eth0的网卡
在本机会生成一个类似vethe1abf09@if26的网卡与容器中的网卡相对应。
只要多一个容器就会多一个veth。也就是说一端在容器里,另一端在本机里,作为连通的作用。 并且, 网络命名空间会将不同的网络隔离开来,各用个的。这样就实现了隔离,以及怎样与本机进行交互。这样,容器和容器之间就可以通讯了。 这解决的是容器和容器间进行通讯。 这是通过docker0网桥解决的
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -o docker0 -j MASQUERADE 这是一个典型的SNAT转换, 这种方式是通过TNAT的方式实现的
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地址呢?接下来就看看有哪些值能被我们修改
docker进程修改, 后面的容器都会跟着被修改. 相当于是主程序修改, 相应的容器都会跟着修改
也就是说, 我们的网桥是docker0, 如果你想要吧网桥改成docker1, 怎么改呢?设置一个参数--bridge="docker1"就可以了
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端口, 默认主机也有这个端口, 所以可以直接访问.
/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进行访问.
那么,如果我不想让他们之间相互访问, 怎么办呢? 这就是容器和容器之间网络隔离
所谓容器间网络隔离, 指的是容器和容器之间网络不通, 也就是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
接下来,我们使用新的网络新建两个容器
docker run -it --name tomcat1 --network=lamp tomcat9 /bin/bash
进入到容器以后, 输入ip a查看容器的ip地址
我们看到容器的ip地址是172.18.0.2
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
比如: 让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的网桥
下面, 设置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, 可以和各种主机/容器进行通讯了.