虚拟机是面向操作系统的,docker是面向应用的,docker容器被设计只运行一个主要进程,即“一个容器一个服务”,容易通过单一职责原则实现关注点分离。容器的隔离性好,但是容器之间有通信的需求,以前笔者创建容器是通过默认的bridge网络,默认的网络是不支持指派固定IP的,IP地址分配和容器启动顺序有关,docker的容器重启之后,会自动分配ip,导致一次重启ip变化。
先来使用bridge网络指定固定IP地址拉起nginx容器,发现提示:user specified IP address is supported on user defined networks only. 要指定固定IP地址就需要在 Docker 中创建自定义网络。那么这一章节就来自建docker 网络。

以前笔者泄露文章-Docker应用:容器间通信与Mariadb数据库主从复制,里面有Docker网络的简单介绍,今天笔者来测试Docker的自建网络。
网络隔离性有两种:
1、个体沙盒-每个容器具有各自用于监听的IP地址和端口,不会与其他容器或宿主机发生重叠;
2、群组沙盒-使用隔离的容器都被分组在同一个私有网络中,可以在不干扰主机网络的情况下进行通信。
通过docker network ls查看docker网络,有三种模式:
bridge:桥接(docker默认);
none:不配置网络;
host:和宿主机共享网络。
自己创建网络的命令是docker network create,可以通过docker network create --help查看命令使用方法。

自己创建网络,也用bridge桥接模式,bridge是docker0的Name,创建网络的时候就应该避开bridge这个名字。
创建my_bridge_network网络, bridge模式,子网172.168.0.0/24,网关172.168.0.1 。注意网络段不要和主机网络段冲突,要不然会影响宿主机。
docker network create --driver bridge --subnet 172.168.0.0/24 --gateway 172.168.0.1 my_bridge_network

也可以通过docker network inspect my_bridge_network查看这个网络的具体信息。在宿主机上,ip addr可以查看到br-开头的网络,地址是my_bridge_network的网关172.168.0.1。这就是桥接模式。
使用这个网络来运行两个nginx容器,docker network inspect my_bridge_network查看两容器的IP地址。笔者昨晚测试完后来发现其实使用 busybox、alpine或者ubuntu镜像来测试比较好,里面工具很多,直接查看容器的IP地址就行,比如docker exec busybox ip addr。
docker run -itd --name nginx1 -p 8081:80 --net my_bridge_network nginx
docker run -itd --name nginx2 -p 8082:80 --net my_bridge_network nginx

进入容器内部,nignx容器内部自带curl工具,测试bridge桥接网络。
1、curl 172.168.0.3、curl 172.168.0.2都可以访问my_bridge_network网络,因为是自建网络(默认的bridge不能使用容器名)可以使用容器名称代替IP地址,curl nginx2,curl nginx1 。
2、curl 10.0.2.15:8081可以宿主机网络。
3、curl www.baidu.com访问外部网络。
但是使用默认的bridge网络再拉一个容器:docker run -itd --name nginx1 -p 8080:80 nginx ,在两个网络的容器是不能相互访问的。
那么bridge的docker0网络中的一个容器如何访问my_bridge_network网络?docker network connect可以连接容器到网络。
docker network connect my_bridge_network nginx
docker network inspect my_bridge_network查看nginx已经加入到 my_bridge_network网络中,在三个容器中就可以相互访问,并可以使用容器名。
最后我们来使用自建的网络指定IP地址再来拉起nginx容器成功。可以通过docker network inspect my_bridge_network查看nginx1的地址为172.168.0.2。多拉几个,按不同顺序启动,IP地址也不会变。

总结:
1、默认Bridge只能使用IP地址通信;
2、自建Bridge网络可以使用容器名和IP地址来通信;
3、容器无法跨网桥网络相互访问;
4、跨多网桥的容器可以使用容器名和IP地址来访问所属任意网络上的容器;
题外话:今天笔者重新装了visualbox的虚拟机ubuntu20上,安装了docker后发现docker变了,可以设置rootless,估计是受红帽podman的影响。操作一番,其实就是创建用户的.service文件。具体可以参考笔者的文章-docker/podman容器自启动设置。在docker官网可以搜索文章Run the Docker daemon as a non-root user来具体查看。


网友评论