1.Docker网络

docker的网络功能还是相对薄弱的。
docker安装后会自动创建3种网络:bridge、host、none

1.1桥接网络

前提:

将前面的docker-compose仓库停掉
docker-compose stop

安装桥接网络

yum install bridge-utils -y
brctl show

docker 桥接 windows docker 桥接 端口_自定义


docker run -d --name demo nginx

docker inspect demo 查看信息ip为 0.2

docker 桥接 windows docker 桥接 端口_自定义_02

docker run -it --rm busybox

ip addr ##ip为0.3

docker 桥接 windows docker 桥接 端口_docker 桥接 windows_03

1.2.host网络模式

docker run -d --name demo --network host nginx

查看端口可以发现docker运行的镜像nginx占用的是80端口

docker 桥接 windows docker 桥接 端口_docker 桥接 windows_04

参数 –network host会占用虚拟机的80端口. 别的nginx不会使用80端口

1.3.none模式

docker run -it --rm --network none busybox

docker 桥接 windows docker 桥接 端口_docker 桥接 windows_05

只有lo接口

2.自定义网络

2.1.创建自定义网桥

建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。

创建网桥 查看类型为bridge

docker network create mynet1 (默认创建桥接)或 docker network create -d bridge mynet1
docker network ls

docker 桥接 windows docker 桥接 端口_自定义_06


测试:docker run -d --name demo1 --network mynet1 nginx

docker run -it --rm --network mynet1 busybox

docker 桥接 windows docker 桥接 端口_docker_07


docker 桥接 windows docker 桥接 端口_运维_08

ping demo1

docker 桥接 windows docker 桥接 端口_docker_09

可以ping demo可以直接成功,说明此模式可以给提供解析
并且系统会自动分配ip,按照启动顺序ip单调递增,但是ping名称的时候会自动解析地址

2.2.自定义网段

docker network rm mynet1    
docker network create -d bridge --subnet 10.0.0.0/24 --gateway 10.0.0.1 mynet1

docker inspect mynet1 ##查看信息

docker 桥接 windows docker 桥接 端口_运维_10

2.3.手动指定ip

使用–ip参数可以指定容器ip地址,但必须是在自定义网桥上
docker run -d --name web1 --network mynet1 nginx
docker run -it --rm --network mynet1 busybox

/ # ip addr
254: eth0@if255: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:0a:00:00:03 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.3/24 brd 10.0.0.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping web1
PING 10.0.0.1 (10.0.0.2): 56 data bytes
64 bytes from 10.0.0.2: seq=0 ttl=64 time=0.043 ms
64 bytes from 10.0.0.2: seq=1 ttl=64 time=0.042 ms
--- 10.0.0.1 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.042/0.042/0.043 ms

cat /etc/hosts

docker 桥接 windows docker 桥接 端口_docker_11

自动解析

也可以ping通网关

2.4.双网卡来实现不同网段间通信

桥接到不同网桥上的容器,彼此是不通信的。

docker network create -d bridge --subnet 20.0.0.0/24 --gateway 20.0.0.1 mynet2

docker run -it --rm --network mynet2 busybox

docker 桥接 windows docker 桥接 端口_docker_12

ping不通

docker ps

docker 桥接 windows docker 桥接 端口_运维_13

docker network connect mynet1 elastic_brahmagupta 后

ping web1/web2

docker 桥接 windows docker 桥接 端口_运维_14

成功

原理是在 busybox中添加了10.0.0的ip

docker 桥接 windows docker 桥接 端口_nginx_15

3.Docker容器通信

容器之间除了使用ip通信外,还可以使用容器名称通信。
dns解析功能必须在自定义网络中使用。
在容器创建时使用–network container:web1指定。

docker run -it --rm --network container:web1 busyboxplus

处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信。

curl localhost

docker 桥接 windows docker 桥接 端口_运维_16

–link 可以用来链接2个容器。
–link的格式:
–link **:alias
name是源容器的name,alias是源容器在link下的别名。

docker run -d --name web1 nginx
 docker run -it --rm --link web1:nginx busyboxplus

ping web1

docker 桥接 windows docker 桥接 端口_运维_17

cat /etc/hosts

docker 桥接 windows docker 桥接 端口_运维_18

env

docker 桥接 windows docker 桥接 端口_运维_19


再次打开一个终端链接server5

docker stop web1
docker run -d --name web2 nginx
docker start web1

我们再一次ping,发现ip变了(由 172.17.02 >>172.17.0.4),但是仍然可以ping名字web1 或nginx 成功 说明它i的名字随着IP实时更新变化的
这时我们查看/etc/hosts,也已经给我们自动修改了解析

127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.4	nginx cc04bfdcf946 web1
172.17.0.3	01239d8f8819

3.1.内部访问外部

容器内部也是可以访问外部网络的

sysctl -a | grep ip_forward

docker 桥接 windows docker 桥接 端口_docker 桥接 windows_20

我们在容器里面可以ping baidu.com

docker run -it --rm --link web1:nginx busybox
ping baidu.com

docker 桥接 windows docker 桥接 端口_nginx_21

3.2.外部访问内部

容器如何访问外网是通过iptables的SNAT实现的

外网访问容器
端口映射
-p 选项指定映射端口
先删除之前的容器

docker run -d --name web1 -p 80:80 nginx

iptables -t nat -nL

docker 桥接 windows docker 桥接 端口_运维_22

netstat -antlp 发现有docker-proxy

docker 桥接 windows docker 桥接 端口_运维_23

3.2.1原理

外网访问容器用到了docker-proxy和iptables DNAT

宿主机访问本机容器使用的是iptables DNAT

外部主机访问容器或容器之间的访问是docker-proxy实现

测试:

curl 172.25.76.5

curl localhost

docker 桥接 windows docker 桥接 端口_自定义_24


现在尝试将iptables里面的策略删除,再次测试

iptables -t nat -F
iptables -t nat -nL

docker 桥接 windows docker 桥接 端口_运维_25

curl localhost

docker 桥接 windows docker 桥接 端口_docker 桥接 windows_26

是因为docker-proxy还在

如果将docker-proxy进程杀掉 就没了

docker 桥接 windows docker 桥接 端口_docker_27

kill -9 28716 28721

再次访问

docker 桥接 windows docker 桥接 端口_nginx_28

当我们重新开启docker

iptables 会重新生成

systemctl restart docker
iptables -t nat -I POSTROUTING -s 172.17.0.0/16 -j MASQUERADE

`curl 172.25.76.5

docker 桥接 windows docker 桥接 端口_自定义_29


又可以访问到nginx的发布页面

从结果得知:

docker-proxy,iptables里面的策略至少需要存在一个才可以

4.创建macvlan网络

实验环境构建:
server5(原虚拟机):
cat /etc/yum.repos.d/dvd.repo

[dvd]
name=rhel7.6
baseurl=http://172.25.76.250/rhel7.6
gpgcheck=0

[docker]
name=docker-ce
baseurl=http://172.25.76.250/20
gpgcheck=0
scp /etc/yum.repos.d/dvd.repo root@172.25.76.4:/etc/yum.repos.d/
scp /etc/sysctl.d/docker.conf server4:/etc/sysctl.d/

server4:
yum install docker-ce -y 安装
systemctl enable --now docker
安装docker的步骤略过 请看上一篇博客
加busyboxplus
docker pull radial/busyboxplus
docker tag radial/busyboxplus:latest busyboxplus:latest
docker rmi radial/busyboxplus:latest

4.1.使用eth1网卡来通信

server4(5):都需要做同样的操作

都添加一个网卡

docker 桥接 windows docker 桥接 端口_运维_30

ip addr show eth1 #查看ip

docker 桥接 windows docker 桥接 端口_nginx_31

cp /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth1

vim /etc/sysconfig/network-scripts/ifcfg-eth1

BOOTPROTO=none
ONBOOT=yes
DEVICE=eth1

ip link set eth1 promisc on

ifup eth1

发现ip addr的eth1出现了promisc模式

docker 桥接 windows docker 桥接 端口_自定义_32

server5:

将之前实验的网络桥接删除掉

docker 桥接 windows docker 桥接 端口_运维_33


先在server5上创建指定条件的容器然后运行容器:

docker network  create -d macvlan --subnet 10.0.0.0/24 --gateway=10.0.0.1 -o parent=eth1 macvlan1
docker run -it --rm --network macvlan1 --ip 10.0.0.10 busyboxplus
ip addr

docker 桥接 windows docker 桥接 端口_docker_34

在server4上:

创建容器并运行和server5操作一样(只有IP不一致!)!

docker network  create -d macvlan --subnet 10.0.0.0/24 --gateway=10.0.0.1 -o parent=eth1 macvlan1
docker run -it --rm --network macvlan1 --ip 10.0.0.11 busyboxplus
ip addr

docker 桥接 windows docker 桥接 端口_docker_35

测试:

在server5上的docker去ping一下server4的docker的ip地址:

server5:

docker run -d  --name web1 --network macvlan1 --ip 10.0.0.10 nginx

server4:

docker run -it --rm --network macvlan1 --ip 10.0.0.11 busyboxplus

ping 10.0.0.10

docker 桥接 windows docker 桥接 端口_自定义_36

curl 10.0.0.10

docker 桥接 windows docker 桥接 端口_docker 桥接 windows_37

成功

也可用虚拟VLAN 网卡进行实验:
在server4和server5:

docker network create -d macvlan --subnet 20.0.0.0/24 --gateway 20.0.0.1 -o parent=eth1.1 macvlan2
ip addr

docker 桥接 windows docker 桥接 端口_docker 桥接 windows_38

在server5上创建一个ip为20.0.0.10 而server4则为20.0.0.11的容器

[root@server5 ~]# docker run -it --rm --network macvlan2 --ip 20.0.0.10 busyboxplus
[root@server4 ~]# docker run -it --rm --network macvlan2 --ip 20.0.0.11 busyboxplus

ipaddr

查看ip

server5:

docker 桥接 windows docker 桥接 端口_docker_39

server4:

ping 20.0.0.10

docker 桥接 windows docker 桥接 端口_自定义_40

成功

结论

不同网段的ip无法互通 但两个处于不同网段的容器可以通过docker network connect macvlan1 的方式来生成同一网段IP地址的方式来实现容器间的通信。


关于虚拟VLAN网卡:
虚拟VLAN网卡也不是实际上的网络接口设备,也可以作为网络接口在系统中出现,但他们没有自己的配置文件而只是通过将物理网加入不同的VLAN而生成的VLAN虚拟网卡。它们的网络接口名是eth0.1、eth1.1这种名字。

注:当需要启用VLAN虚拟网卡工作的时候,关联的物理网卡网络接口上必须没有IP地址的配置信息,并且,这些主物理网卡的子网卡也必须不能被启用和必须不能有IP地址配置信息。