一:如何让一个容器连接两个网络?
如果是使用 docker run,那很不幸,一次只可以连接一个网络,因为 docker run 的 --network 参数只可以出现一次(如果出现多次,最后的会覆盖之前的)。不过容器运行后,可以用命令 docker network connect 连接多个网络。
假设我们创建了两个网络:
$ docker network create mynet1
$ docker network create mynet2
然后,我们运行容器,并连接这两个网络。
$ docker run -d --name web --network mynet1 nginx
$ docker network connect mynet2 web
但是如果使用 docker-compose 那就没这个问题了。因为实际上,Docker Remote API 是支持一次性指定多个网络的,但是估计是命令行上不方便,所以 docker run 限定为只可以一次连一个。docker-compose 直接就可以将服务的容器连入多个网络,没有问题。
version: '2'
services:
web:
image: nginx
networks:
- mynet1
- mynet2
networks:
mynet1:
mynet2:
二:Docker 多宿主网络怎么配置?
Docker 跨节点容器网络互联,最通用的是使用 overlay 网络。
一代 Swarm 已经不再使用,它要求使用 overlay 网络前先准备好分布式键值库,比如 etcd, consul 或 zookeeper。然后在每个节点的 Docker 引擎中,配置 --cluster-store 和 --cluster-advertise 参数。这样才可以互连。可以参考我写的 LNMP 容器互联例子中的 run1.sh 这个脚本,这个脚本是利用 docker-machine自动建立 Swarm 并且配置好 overlay 的脚本,可以分析其流程。
现在都在使用二代 Swarm,也就是 Docker Swarm Mode,非常简单,只要 docker swarm init 建立集群,其它节点 docker swarm join 加入集群后,集群内的服务就自动建立了 overlay 网络互联能力。
需要注意的是,如果是多网卡环境,无论是 docker swarm init 还是 docker swarm join,都不要忘记使用参数 --advertise-addr 指定宣告地址,否则自动选择的地址很可能不是你期望的,从而导致集群互联失败。格式为 --advertise-addr <地址>:<端口>,地址可以是 IP 地址,也可以是网卡接口,比如 eth0。端口默认为 2377,如果不改动可以忽略。
此外,这是供服务使用的 overlay,因此所有 docker service create 的服务容器可以使用该网络,而 docker run 不可以使用该网络,除非明确该网络为 --attachable。
关于 overlay 网络的进一步信息,可以参考官网文档:https://docs.docker.com/engine/userguide/networking/get-started-overlay/
虽然默认使用的是 overlay 网络,但这并不是唯一的多宿主互联方案。Docker 内置了一些其它的互联方案,比如效率比较高的 macvlan。如果在局域网络环境下,对 overlay 的额外开销不满意,那么可以考虑 macvlan 以及 ipvlan,这是比较好的方案。https://docs.docker.com/engine/userguide/networking/get-started-macvlan/
此外,还有很多第三方的网络可以用来进行跨宿主互联,可以访问官网对应文档进一步查看:https://docs.docker.com/engine/extend/legacy_plugins/#/network-plugins