如今Docker的使用已经非常普遍,特别在一线互联网公司。使用Docker技术可以帮助企业快速水平扩展服务,从而到达弹性部署业务的能力。在云服务概念兴起之后,Docker的使用场景和范围进一步发展。今天,就让我们来看看关于Docker的深度问答。
Q:vethxxxx 这种虚拟网卡和容器的对应关系从哪里看?
A:使用如下命令:
注意这里的 br-56f04389b8f0 以及 br-094fcb269385,br- 后面的是上面的网络id,由此可以看出 veth 和 Docker 网络的对应关系,而容器都是连接到了某个Docker网络上的,从而就有了容器和 veth 的对应关系。对于某个网络出现了多个veth 的情况,可以观察veth22996d2@if11 后面的 if11 这部分,和容器内的 ip addr 的结果,一般奇-偶是一对。
Q:如何让一个容器连接两个网络?
A:如果是使用 docker run,那很不幸,一次只可以连接一个网络,因为 docker run 的 --network 参数只可以出现一次(如果出现多次,最后的会覆盖之前的)。不过容器运行后,可以用命令 docker network connect 连接多个网络。假设我们创建了两个网络:
3Q:Docker 多宿主网络怎么配置
A: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。
Q:明明 docker network ls 中看到了建立的 overlay 网络,怎么docker run 还说网络不存在啊?
A:如果在 docker network ls 中看到了如下的 overlay 网络:
报错说mynet 网络找不到。其实如果仔细观察,会看到这个名为mynet 的网络,驱动是 overlay没有错,但它的Scope 是swarm。这个意思是说这个网络是在二代Swarm环境中建立的overlay网络,因此只可以由Swarm环境下的服务容器才可以使用。而docker run所运行的只是零散的容器,并非Service,因此自然在零散容器所能使用的网络中,不存在叫mynet网络。
docker run可以使用的overlay网络是Scope为global的overlay网络,也就是使用外置键值库所建立的overlay网络,比如一代Swarm的overlay网络。这点在 1.13 后稍有变化。如果是 1.13 以后的系统,会看到这样的信息:
Q:容器怎么取宿主机 IP 啊?
A:单机环境
如果是单机环境,很简单,不必琢磨怎么突破命名空间限制,直接用环境变量送进去即可。
然后容器内直接读取 HOST_IP 环境变量即可。
集群环境
集群环境相对比较复杂,docker service create 中的 -e 以及 --env-file是在服务创建时指定、读取环境变量内容,而不是运行时,因此对于每个节点都是一样的。而且目前不存在 dockerd -e 选项,所以直接使用这些选项达不到我们想要的效果。不过有变通的办法,可以在宿主上建立一个 /etc/variables 文件(名字随意,这里用这个文件举例)。其内容为:
其中 1.2.3.4 是这个节点的宿主 IP,因此每个节点的 /etc/variables 的内容不同。
而在启动服务时,指定挂载这个服务端本地文件:
docker service create --name app \
--mount type=bind,source=/etc/variables,target=/etc/variables:ro \
myapp
由于 --mount 是发生于容器运行时,因此所加载的是所运行的服务器的 /etc/variables,里面所包含的也是该服务器的 IP 地址。在 myapp 这个镜像的入口脚本加入加载该环境变量文件的命令:
这样app这个服务容器就会拥有 HOST_IP 环境变量,其值为所运行的宿主 IP。
小伙伴们冲鸭,后台留言区等着你!
关于Docker,今天你学到了什么?还有哪些不懂的?除此还对哪些话题感兴趣?快来留言区打卡啦!留言方式:打开第XX天,答:……
同时欢迎大家搜集更多问题,投稿给我们!风里雨里留言区里等你~
福利
1、扫描添加小编微信,备注“姓名+公司职位”,加入【云计算学习交流群】,和志同道合的朋友们共同打卡学习!
2、公众号后台回复:白皮书,获取IDC最新数据白皮书整理资料!
推荐阅读: