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
- 查看网桥的信息:
bridge show
- 将webserver打入后台运行:
docker run -d --name demo webserver
- 查看网桥:
brctl show
1.1 host模式
host模式可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性
(1)host网络模式需要在容器创建时指定 :docker run -it --rm --network=host busybox
,查看容器的ip和网关,此时容器使用的是宿主机的ip和网关,可以实现容器和外部主机的通信
(2) 在后台运行webserver镜像的容器:docker run -d --name demo1 --network=host webserver
- 查看主机的ip:
ip addr
- 查看服务和端口号:
netstat -antlp
,此时webserver的服务被映射到本地的80端口,可以通过访问宿主机来访问容器
(3)在后台运行容器demo2:docker run -d --name demo2 --network=host webserver
- 如果不指定容器和宿主机映射的端口号,nginx服务的端口将默认映射到本地的80端口,但是此时本地的80端口已经被demo1占用,运行demo2容器会自动结束服务
- 查看demo2的日志信息:
docker logs b24ef540d904
1.2 none模式
- none模式是指禁用网络功能,只有lo接口,在容器创建时使用
docker run -it --network none busybox
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地址递增)
(2)删除容器demo2(ip会被回收)
docker ps -a
docker rm -f demo2
(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
2 Docker自定义网络
自定义网络模式,docker提供了三种自定义网络驱动:bridge、overlay、macvlan
bridge驱动类似默认的bridge网络模式,但增加了一些新的功能,
overlay和macvlan是用于创建跨主机网络。
2.1 自定义网桥
(1)列出docker的网桥:docker network ls
(2)创建自定义网桥:docker network create mynet
- 查看自定义网桥mynet的信息:
docker inspect mynet
(3) 运行容器时指定网桥:docker run -it --name demo1 --network=mynet busybox
,deo1容器使用的是mynet的网桥,被分配到的是mynet的网段(退出不结束容器)
- 运行demo2容器时指定网桥:
docker run -it --name demo2 --network=mynet busybox
##ip自动分配的规则也是自动递增的,一旦容器停止ip地址也被回收
- 在容器demo2中可以ping通172.18.0.2和demo1,使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址
- 如果容器名称对应的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
- 在demo2容器中
ping demo1
,demo1的ip会被自动解析到172.18.0.3
docker ps -a ##查看docker所有状态的容器
docker attach 9818bbe3e34e ##进入容器demo2
ping demo1
2.2 创建自定义网络时指定参数
(1) 创建自定义网桥net1时指定子网和网关
docker network create --subnet 172.20.0.0/24 --gateway 172.20.0.1 net1
--subnet
- 查看docker的网桥:docker network ls
- 查看net1的信息:
docker inspect net1
,被分配到的子网和网关时在创建时被指定的
- 查看宿主机的网络信息:
ip addr
,自定义的网桥被添加到宿主机
(2) 运行容器时指定网桥net1,容器的ip属于net1的网段,ip自动分配的原则是依次递增
docker run -it --rm --network net1 busybox
(3) 使用--ip参数可以指定容器ip地址,但必须是在自定义网桥上
,默认的bridge模式不支持,只有同一网桥上的容器是可以互通的,桥接到不同网桥上的容器,彼此是不通信的。
- 指定容器的ip和网桥:
docker run -it --rm --ip 172.20.0.30 --network net1 busybox
- 将容器demo打入到后运行:
docker run -d --name demo webserver
- 查看demo的信息:
docker inspect demo
- 进入vigorous_chaplygin容器:
docker attach 85d3f9c38c76
,由于vigorous_chaplygin容器和demo1容器不在同一个网桥上,不能通信
(4)解决两个不同网桥的容器通信,可以通过docker network connect
命令为demo添加一块net1 的网卡,从而实现两个不同网桥的容器通信
- 在后台运行demo容器:
docker run -d --name demo webserver
- 查看demo的信息:
docker inspect demo
- demo容器添加net1:
docker network connect net1 demo
- 查看demo的信息:
docker inspect demo
,有两个网卡的信息
- 运行容器时指定net1网卡:
docker run -it --rm --network net1 busybox
,此时可以实现两个网桥容器的通信
3 Docker容器通信
3.1 Joined容器
(1)Joined容器一种较为特别的网络模式,它可以使两个或多个容器共享一个网络栈,共享网卡和配置信息
- 查看docker所有状态的容器:
docker ps -a
- 运行容器时指定和demo容器共享网络栈
docker run -it --rm --network container:demo busybox
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解析
- 容器的dns解析文件:
cat /etc/hosts
- demo容器停止服务:
docker stop demo
,此时nginx服务ping不通
- 运行demo1容器:
docker run -d --name demo1 nginx
- 查看demo1的信息:
docker inspect demo1
,demo1的ip是172.17.0.2,
- 运行demo容器:
docker start demo
,查看demo的信息:docker inspect demo
,此时demo的ip是172.12.0.4,dns随之更新,在容器内ping nginx服务被解析到172.17.0.4
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已经开启
- 查看容器demo的详细信息:
docker inspect demo
- iptables的规则:
iptables -t nat -nL
- 容器的服务可以在本地访问:
curl localhost
- 远程主机访问:
curl 172.25.12.2
(2) 删除DNAT规则: iptables -t nat -D DOCKER 3
,docker proxy可以替代DNAT,删除DNAT规则后容器和容器之间、容器和宿主机、容器和远程主机人然可以正常通信
- docker proxy仍然在提供服务:
netstat -antlp
- 本地可以访问容器的服务:
curl localhost
- 远程主机也可以访问容器的服务:
curl 172.25.12.2
- 运行容器demo1,并将服务的端口映射到本地的8080端口:
docker run -d --name demo1 -p 8080:80 nginx
- 查看服务和端口号:netstat -antlp
- 本地可以访问8080端口:
curl localhost:8080
- 在远程主机也可以通过访问宿主机的8080端口访问容器的服务:
curl 172.25.12.2:8080
- 下载busyboxplus镜像:
docker pull busyboxplus
- 运行容器:
docker run -it --rm busyboxplus
- 在运行busyboxplus镜像的容器中访问demo容器的nginx服务:
curl 172.17.0.2
- 在运行busyboxplus镜像的容器中访问demo1容器的nginx服务:
curl 172.17.0.3
(3) 关闭demo1的docker proxy服务(容器和宿主机之间不能正常通信)
netstat -antlp ##查看服务和端口号
kill 9876
- demo1的DNAT规则正常工作:
iptables -t nat -nL
- 容器内可以访问demo1容器的服务:
curl 172.17.0.3
- demo1的服务不能通过宿主机访问:
curl localhost:8080
- 远程主机可以访问demo1容器的服务:
curl 172.25.12.2:8080
(4) 删除DNAT规则: iptables -t nat -D DOCKER 3
,docker proxy已经停止工作,此时只有容器之间可以正常通信
- 容器内可以访问demo1容器的服务:
curl 172.17.0.3
- demo1的服务不能通过宿主机访问:
curl localhost:8080
- 远程主机不能访问demo1容器的服务:
curl 172.25.12.2:8080
4 跨主机容器网络
4.1 macvlan网络方案实现
Linux kernel提供的一种网卡虚拟化技术。不需要Linux bridge,直接使用物理接口,性能极好。
(1) 在server1和server2两台docker主机上各添加一块网卡,打开网卡混杂模式
ip link set enp7s0 promisc on ##打开网卡混杂模式
ip addr
(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的桥接口
- 容器的接口直接与主机网卡连接,无需NAT或端口映射:
brctl show
- 查看mac_net1 网络的信息:
docker inspect mac_net1
测试:
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
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
(3) macvlan网络间的隔离和连通
- macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的。 可以在三层上通过网关将macvlan网络连通起来。