Docker网络

  • 1 Docker原生网络
  • 1.1 host模式
  • 1.2 none模式
  • 1.3 Docker网络ip分配的原则
  • 2 Docker自定义网络
  • 2.1 自定义网桥
  • 2.2 创建自定义网络时指定参数
  • 3 Docker容器通信
  • 3.1 Joined容器
  • 3.2 --link
  • 3.3 外网访问容器
  • 4 跨主机容器网络
  • 4.1 macvlan网络方案实现
  • 4.2 多macvlan网络


1 Docker原生网络

docker安装后会自动创建3种网络:bridge、host、none

docker安装时会创建一个名为 docker0 的Linux bridge,新建的容器会自动桥接到这个接口

  • 运行容器:docker run -it --rm busybox

docker 搭建网络 docker 创建网络_自定义

  • 查看网桥的信息:bridge show

docker 搭建网络 docker 创建网络_docker 搭建网络_02

  • 将webserver打入后台运行:docker run -d --name demo webserver
  • 查看网桥: brctl show

docker 搭建网络 docker 创建网络_自定义_03

1.1 host模式

host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性

(1)host网络模式需要在容器创建时指定 :docker run -it --rm --network=host busybox,查看容器的ip和网关,此时容器使用的是宿主机的ip和网关,可以实现容器和外部主机的通信

docker 搭建网络 docker 创建网络_nginx_04

docker 搭建网络 docker 创建网络_nginx_05

(2) 在后台运行webserver镜像的容器:docker run -d --name demo1 --network=host webserver

  • 查看主机的ip:ip addr

docker 搭建网络 docker 创建网络_docker_06

  • 查看服务和端口号:netstat -antlp,此时webserver的服务被映射到本地的80端口,可以通过访问宿主机来访问容器

docker 搭建网络 docker 创建网络_自定义_07

docker 搭建网络 docker 创建网络_docker 搭建网络_08

(3)在后台运行容器demo2:docker run -d --name demo2 --network=host webserver

  • 如果不指定容器和宿主机映射的端口号,nginx服务的端口将默认映射到本地的80端口,但是此时本地的80端口已经被demo1占用,运行demo2容器会自动结束服务

docker 搭建网络 docker 创建网络_自定义_09

  • 查看demo2的日志信息:docker logs b24ef540d904

docker 搭建网络 docker 创建网络_docker 搭建网络_10

1.2 none模式

  • none模式是指禁用网络功能,只有lo接口,在容器创建时使用
docker run -it --network none busybox

docker 搭建网络 docker 创建网络_自定义_11

1.3 Docker网络ip分配的原则

运行容器时,docker为容器默认分ip的规则是在docker0网桥的基础上递增的,一旦容器停止工作,容器被分配的ip地址也会被回收

(1)运行容器demo1和demo2

docker run -it --name demo1  busybox
##demo1被分配到的ip是172.12.0.3,ctrl+p+q退出容器,不结束
docker run -it --name demo2  busybox
##demo2运行后,分配到的ip是172.12.0.3(ip地址递增)

docker 搭建网络 docker 创建网络_nginx_12


(2)删除容器demo2(ip会被回收)

docker ps -a
docker rm -f demo2

docker 搭建网络 docker 创建网络_自定义_13


(3)运行容器demo3:docker run -it --name demo3 busybox,分配到的ip是172.17.0.3,退出demo3(ctrl+p+q)

  • 运行容器demo2:dockun -it --name demo2 busybox,分配到的ip是172.17.0.4

docker 搭建网络 docker 创建网络_docker_14

2 Docker自定义网络

自定义网络模式,docker提供了三种自定义网络驱动:bridge、overlay、macvlan
bridge驱动类似默认的bridge网络模式,但增加了一些新的功能,
overlay和macvlan是用于创建跨主机网络。

2.1 自定义网桥

(1)列出docker的网桥:docker network ls

docker 搭建网络 docker 创建网络_docker_15

(2)创建自定义网桥:docker network create mynet

docker 搭建网络 docker 创建网络_docker 搭建网络_16

  • 查看自定义网桥mynet的信息:docker inspect mynet

docker 搭建网络 docker 创建网络_自定义_17


(3) 运行容器时指定网桥:docker run -it --name demo1 --network=mynet busybox,deo1容器使用的是mynet的网桥,被分配到的是mynet的网段(退出不结束容器)

docker 搭建网络 docker 创建网络_nginx_18

  • 运行demo2容器时指定网桥:
docker run -it --name demo2 --network=mynet busybox
##ip自动分配的规则也是自动递增的,一旦容器停止ip地址也被回收
  • 在容器demo2中可以ping通172.18.0.2和demo1,使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址

docker 搭建网络 docker 创建网络_nginx_19

  • 如果容器名称对应的ip地址发生变化,使用自定义的网络可以自动更新DNS解析容器名称到IP地址
  • 删除demo1容器:docker rm -f demo1
  • 运行demo3容器和demo1容器,此时demo1会被分配到新的ip
docker run -it --name demo3 --network=mynet busybox
docker run -it --name demo1 --network=mynet busybox

docker 搭建网络 docker 创建网络_自定义_20

  • 在demo2容器中ping demo1,demo1的ip会被自动解析到172.18.0.3
docker ps -a ##查看docker所有状态的容器
docker attach 9818bbe3e34e  ##进入容器demo2
ping demo1

docker 搭建网络 docker 创建网络_docker_21

docker 搭建网络 docker 创建网络_docker_22

2.2 创建自定义网络时指定参数

(1) 创建自定义网桥net1时指定子网和网关

docker network create --subnet 172.20.0.0/24 --gateway 172.20.0.1 net1 
--subnet
  • 查看docker的网桥:docker network ls

docker 搭建网络 docker 创建网络_自定义_23

  • 查看net1的信息:docker inspect net1,被分配到的子网和网关时在创建时被指定的

docker 搭建网络 docker 创建网络_docker 搭建网络_24

  • 查看宿主机的网络信息:ip addr,自定义的网桥被添加到宿主机

docker 搭建网络 docker 创建网络_docker 搭建网络_25

(2) 运行容器时指定网桥net1,容器的ip属于net1的网段,ip自动分配的原则是依次递增

docker run -it --rm --network net1 busybox

docker 搭建网络 docker 创建网络_自定义_26


(3) 使用--ip参数可以指定容器ip地址,但必须是在自定义网桥上,默认的bridge模式不支持,只有同一网桥上的容器是可以互通的,桥接到不同网桥上的容器,彼此是不通信的。

  • 指定容器的ip和网桥:docker run -it --rm --ip 172.20.0.30 --network net1 busybox

docker 搭建网络 docker 创建网络_nginx_27

  • 将容器demo打入到后运行:docker run -d --name demo webserver
  • 查看demo的信息:docker inspect demo

docker 搭建网络 docker 创建网络_docker_28

  • 进入vigorous_chaplygin容器:docker attach 85d3f9c38c76,由于vigorous_chaplygin容器和demo1容器不在同一个网桥上,不能通信

docker 搭建网络 docker 创建网络_docker_29

(4)解决两个不同网桥的容器通信,可以通过docker network connect命令为demo添加一块net1 的网卡,从而实现两个不同网桥的容器通信

  • 在后台运行demo容器:docker run -d --name demo webserver
  • 查看demo的信息:docker inspect demo

docker 搭建网络 docker 创建网络_nginx_30

docker 搭建网络 docker 创建网络_nginx_31

  • demo容器添加net1: docker network connect net1 demo
  • 查看demo的信息:docker inspect demo,有两个网卡的信息

docker 搭建网络 docker 创建网络_docker 搭建网络_32

  • 运行容器时指定net1网卡: docker run -it --rm --network net1 busybox,此时可以实现两个网桥容器的通信

docker 搭建网络 docker 创建网络_docker 搭建网络_33

3 Docker容器通信

3.1 Joined容器

(1)Joined容器一种较为特别的网络模式,它可以使两个或多个容器共享一个网络栈,共享网卡和配置信息

  • 查看docker所有状态的容器:docker ps -a
  • 运行容器时指定和demo容器共享网络栈
docker run -it --rm --network container:demo busybox

docker 搭建网络 docker 创建网络_docker_34

3.2 --link

link 可以用来链接2个容器

--link的格式:
	--link <name or id>:alias
	name和id是容器的name和id,alias是容器在link下的别名

例如:docker run -it --name demo2 --link demo1 nginx

  • 相当于在demo1和demo2之间添加了一个类似于DNS的记录,使得两个容器之间可以通过容器名来互联。但是docker的link是有方向性的,demo2link到demo1所以在demo2容器中可以ping通demo1,但是在demo1容器中不能通过容器名demo2访问demo2容器。

(1)在后台运行容器:docker run -d --name demo nginx

(2)运行容器并将其link到demo1:docker run -it --rm --link demo:nginx busybox

  • env:查看环境变量
  • ping nginx(demo1容器的别名)自动解析到demo的ip地址,原因是容器中有demo容器的dns解析

docker 搭建网络 docker 创建网络_docker 搭建网络_35

  • 容器的dns解析文件:cat /etc/hosts

docker 搭建网络 docker 创建网络_nginx_36

  • demo容器停止服务:docker stop demo,此时nginx服务ping不通

docker 搭建网络 docker 创建网络_nginx_37


docker 搭建网络 docker 创建网络_nginx_38

  • 运行demo1容器:docker run -d --name demo1 nginx
  • 查看demo1的信息:docker inspect demo1,demo1的ip是172.17.0.2,

docker 搭建网络 docker 创建网络_docker 搭建网络_39

docker 搭建网络 docker 创建网络_nginx_40


docker 搭建网络 docker 创建网络_docker 搭建网络_41

  • 运行demo容器:docker start demo,查看demo的信息:docker inspect demo,此时demo的ip是172.12.0.4,dns随之更新,在容器内ping nginx服务被解析到172.17.0.4

docker 搭建网络 docker 创建网络_自定义_42


docker 搭建网络 docker 创建网络_nginx_43

docker 搭建网络 docker 创建网络_nginx_44

3.3 外网访问容器

实现外网和容器之间的通信,可以在运行容器时将容器服务的端口号映射到宿主机的端口,这样外网可以通过访问宿主机的端口来实现与宿主机内容器的通信

  • 外网访问容器用到了docker-proxy和iptables DNAT
  • 宿主机访问本机容器使用的是iptables DNAT,bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的。容器通过宿主机的NAT规则后可以访问外网
  • 外部主机访问容器或容器之间的访问是docker-proxy实现

(1) 将服务打入后台运行: docker run -d --name demo -p 80:80 nginx,将容器的80端口映射到宿主机的80端口,外网可以通过访问宿主机的相应端口实现与容器的通信

  • 查看服务和端口号: netstat -antlp,docker-proxy已经开启

docker 搭建网络 docker 创建网络_docker 搭建网络_45

  • 查看容器demo的详细信息:docker inspect demo

docker 搭建网络 docker 创建网络_自定义_46

  • iptables的规则:iptables -t nat -nL

docker 搭建网络 docker 创建网络_docker_47

  • 容器的服务可以在本地访问: curl localhost

docker 搭建网络 docker 创建网络_nginx_48

  • 远程主机访问: curl 172.25.12.2

docker 搭建网络 docker 创建网络_docker_49

(2) 删除DNAT规则: iptables -t nat -D DOCKER 3,docker proxy可以替代DNAT,删除DNAT规则后容器和容器之间、容器和宿主机、容器和远程主机人然可以正常通信

docker 搭建网络 docker 创建网络_docker_50

  • docker proxy仍然在提供服务:netstat -antlp

docker 搭建网络 docker 创建网络_nginx_51

  • 本地可以访问容器的服务:curl localhost

docker 搭建网络 docker 创建网络_docker 搭建网络_52

  • 远程主机也可以访问容器的服务:curl 172.25.12.2

docker 搭建网络 docker 创建网络_docker_53

  • 运行容器demo1,并将服务的端口映射到本地的8080端口:docker run -d --name demo1 -p 8080:80 nginx
  • 查看服务和端口号:netstat -antlp

docker 搭建网络 docker 创建网络_docker_54

  • 本地可以访问8080端口:curl localhost:8080

docker 搭建网络 docker 创建网络_自定义_55

  • 在远程主机也可以通过访问宿主机的8080端口访问容器的服务:curl 172.25.12.2:8080

docker 搭建网络 docker 创建网络_自定义_56

  • 下载busyboxplus镜像:docker pull busyboxplus
  • 运行容器:docker run -it --rm busyboxplus
  • 在运行busyboxplus镜像的容器中访问demo容器的nginx服务:curl 172.17.0.2

docker 搭建网络 docker 创建网络_nginx_57

  • 在运行busyboxplus镜像的容器中访问demo1容器的nginx服务:curl 172.17.0.3

docker 搭建网络 docker 创建网络_docker_58

(3) 关闭demo1的docker proxy服务(容器和宿主机之间不能正常通信)

netstat -antlp   ##查看服务和端口号
kill 9876

docker 搭建网络 docker 创建网络_nginx_59

  • demo1的DNAT规则正常工作:iptables -t nat -nL

docker 搭建网络 docker 创建网络_nginx_60

  • 容器内可以访问demo1容器的服务:curl 172.17.0.3

docker 搭建网络 docker 创建网络_自定义_61

  • demo1的服务不能通过宿主机访问:curl localhost:8080

docker 搭建网络 docker 创建网络_nginx_62

  • 远程主机可以访问demo1容器的服务:curl 172.25.12.2:8080

docker 搭建网络 docker 创建网络_自定义_63

(4) 删除DNAT规则: iptables -t nat -D DOCKER 3,docker proxy已经停止工作,此时只有容器之间可以正常通信

docker 搭建网络 docker 创建网络_docker 搭建网络_64

  • 容器内可以访问demo1容器的服务:curl 172.17.0.3

docker 搭建网络 docker 创建网络_docker_65

  • demo1的服务不能通过宿主机访问:curl localhost:8080

docker 搭建网络 docker 创建网络_nginx_66

  • 远程主机不能访问demo1容器的服务:curl 172.25.12.2:8080

docker 搭建网络 docker 创建网络_docker_67

4 跨主机容器网络

4.1 macvlan网络方案实现

Linux kernel提供的一种网卡虚拟化技术。不需要Linux bridge,直接使用物理接口,性能极好。

(1) 在server1和server2两台docker主机上各添加一块网卡,打开网卡混杂模式

ip link set  enp7s0 promisc on ##打开网卡混杂模式
ip addr

docker 搭建网络 docker 创建网络_docker 搭建网络_68

(2) 创建macvlan网络

docker network create -d macvlan --subnet 172.21.0.0/24 --gateway 172.21.0.1 -o parent=enp7s0 mac_net1
docker network ls ##列出docker的网络

docker 搭建网络 docker 创建网络_docker 搭建网络_69

  • 网络创建成功后不会在本地创建docker的桥接口

docker 搭建网络 docker 创建网络_docker_70

  • 容器的接口直接与主机网卡连接,无需NAT或端口映射:brctl show

docker 搭建网络 docker 创建网络_docker_71

  • 查看mac_net1 网络的信息:docker inspect mac_net1

docker 搭建网络 docker 创建网络_自定义_72


测试:

server1:docker run -it --rm --network mac_net1 --ip 172.30.0.11 busybox
server2:docker run -it --rm --network mac_net1 --ip 172.30.0.12 busybox

docker 搭建网络 docker 创建网络_nginx_73

docker 搭建网络 docker 创建网络_nginx_74

4.2 多macvlan网络

macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络
vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1~4094

(1) 创建vlan子接口的macvlan网络:docker network create -d macvlan --subnet 172.31.0.0/24 --gateway 172.31.0.1 -o parent=enp7s0.1 mac_net2 (2) 运行容器:docker run -it --rm --network mac_net2 --ip 172.31.0.12 busybox

docker 搭建网络 docker 创建网络_docker 搭建网络_75


(3) macvlan网络间的隔离和连通

  • macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的。 可以在三层上通过网关将macvlan网络连通起来。