前言
现在绝大部分应用都有支持容器化部署,如 mysql,redis,nginx 等。我们在自己的单机开发测试环境可以非常方便的使用 docker 进行部署。但是有这样的问题,自己分开部署应用时,比如应用连接 mysql 和 redis,以前要么将 mysql, redis 端口映射到宿主机,应用网络配置成 host 模式进行连接或者应用配置它们的容器 ip,但这样重启容器 ip 可能会变,维护非常麻烦。解决这个问题的方案可以使用 docker 的 User-defined bridges 网络,下面开始介绍。
docker network driver
安装好 docker 服务后,默认会有3个 network ,bridge,host 和 none。
bridge: 默认 network driver,当应用程序在需要与同一主机上的其他容器通信的容器中运行时,通常使用桥接网络。host: 移除容器与 Docker 主机之间的网络隔离,直接使用主机的网络。none: 将容器与主机和其他容器完全隔离。使用该 network 创建的容器,仅创建环回设备网卡lo。
另外,用户也可使用 docker network create 命令创建自己的网络,默认 network driver 也是 bridge,你可指定子网,ip 地址范围等其他参数选项,详情可以加上 --help参数查看。
[root@z2024 ~]# docker network create --help
Usage: docker network create [OPTIONS] NETWORK
Create a network
Options:
--attachable Enable manual container attachment
--aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
--config-from string The network from which to copy the configuration
--config-only Create a configuration only network
-d, --driver string Driver to manage the Network (default "bridge")
--gateway strings IPv4 or IPv6 Gateway for the master subnet
--ingress Create swarm routing-mesh network
--internal Restrict external access to the network
--ip-range strings Allocate container ip from a sub-range
--ipam-driver string IP Address Management Driver (default "default")
--ipam-opt map Set IPAM driver specific options (default map[])
--ipv6 Enable IPv6 networking
--label list Set metadata on a network
-o, --opt map Set driver specific options (default map[])
--scope string Control the network's scope
--subnet strings Subnet in CIDR format that represents a network segment
User-defined bridge 与 default bridge 之间的差异
User-defined bridge 与 default bridge 之间的差异,官方列出有以下几点
User-defined bridges在容器之间提供自动 DNS 解析。
default bridge 网络上的容器只能通过 IP 地址相互访问,除非使用 --link 选项,该选项被视为过时的。在 User-defined bridges网络上,容器可以通过名称或别名相互解析。
User-defined bridges提供更好的隔离
所有创建未使用 --network 指定的容器都将连接到默认网桥网络,而使用 User-defined bridges 提供了一个作用域内的网络,在该网络中,只有连接到该网络的容器才能进行通信。
- 容器可以动态地从用户定义的网络中 attached 和 detached
在容器的生命周期内,您可以动态地连接或断开它与用户定义的网络的连接 。要从默认网桥网络中删除容器,您需要停止该容器,然后使用不同的网络选项重新创建它。
- 每个用户定义的网络都会创建一个可配置的网桥。
如果容器使用默认网桥网络,则可以对其进行配置,但所有容器都使用相同的设置,例如 MTU 和 iptables 规则。此外,配置默认网桥网络发生在 Docker 本身之外,并且需要重新启动 Docker。 用户定义的网桥网络是使用 docker network create 创建和配置的。如果不同的应用程序组具有不同的网络要求,则可以在创建每个用户定义的网桥时单独配置网桥。
下面我们做个实验,分别在 User-defined bridge 与 default bridge 网络下创建两个容器,首先创建一个 User-defined bridge 网络名叫 mytest
root@zvps1:~# docker network create mytest
60955eb581f962fac7a50fe3f45c29ef0f626ea7c451c35dc0cafb4547b80dd0
root@zvps1:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
606ce11f6e40 bridge bridge local
8a12b80eed2f host host local
60955eb581f9 mytest bridge local
63d7be2720d7 none null local
创建4个容器,test1 和 test2 属于默认 bridge 网络,test3 和 test4 属于 mytest 网络
# test1 container
docker run --name test1 -d nginx
# test2 container
docker run --name test2 -d nginx
# test3 container
docker run --name test3 --network mytest -d nginx
# test4 container
docker run --name test4 --network mytest -d nginx
可以使用 docker network inspect 命令查看 docker 网络详情,还可以查看到哪些容器使用该网络以及容器 ip 和 mac 地址等信息
使用 busybox 容器测试 default bridge 网络,可以看到它无法解析 test1, test2 容器
使用 busybox 容器测试 mytest 网络,可以看到能解析 test3, test4 容器
Networking in Docker Compose
默认情况下,Compose 会为您的应用设置一个网络,服务的每个容器都加入它,这使得每个容器可以通过服务的名称发现。 例如,假设您的应用位于 myapp 的目录中,运行 docker compose up 时, 将创建一个名为的 myapp_default 网络。
总结
相比于默认的桥接网络,User-defined Bridges 不仅在容器之间提供自动 DNS 解析,还提供了更好的隔离和灵活性,使得容器间的通信更为便捷。Docker Compose 也是基于这一点,使得服务里面的容器可以互相解析。希望这篇文章对你有所帮助,如果你有任何疑问,欢迎留言讨论或者关注我的微信公众号运维小猪,谢谢!