Docker 网络通信: 最佳实践和解决方案

silverwq
2024-03-14 / 0 评论 / 72 阅读 / 正在检测是否收录...

概述

容器内部的网络是独立的,但是有时候又需要不同容器之间的网络进行共享通信。

网络模式

docker 里的网络模式就桥接、host、none三种

docker network ls

ltrcnmg4.png

bridge 桥接

在主机中创建一个docker0的虚拟网桥,主机网卡和docker0连接,在docker0(可以理解为虚拟的交换机)上创建多对虚拟网卡,有一半在主机上vethxxx,一半在容器内eth0。

ltrao9i6.png

外部主机通过访问宿主机的网卡ens160,然后ens160可以访问桥接网卡docker0,docker0上通过ip转发的方式,转发到相应的veth网卡上,这个veth网卡都有相应的容器eth0网卡和它互相通信连接,这样就实现了网络链路的打通。

ltramxab.png

特点:

  1. 容器之间是在同一个子网里,可以互相访问到
  2. 外部网络必须通过主机桥接才能访问到容器,容器得到很好的隔离
  3. 容器之间只能通过ip访问,如果想要通过容器名称访问,需要指定-link参数,而且只能单向访问

实验

以桥接模式启动容器

# --net bridge 指定桥接模式
docker run -d --rm -P --name docker_net1 --net bridge centos ping 127.0.0.1
docker run -d --rm -P --name docker_net2 --net bridge centos ping 127.0.0.1

通过这种模式启动的话docker_net1只能通过ip访问到docker_net2,而不能通过容器名称访问。

 docker exec -it docker_net1 ping 172.17.0.3

lts1oqnf.png

查看docker_net2的ip地址

lts1nf51.png

不过工作中,实际不会通过ip来访问,希望通过容器名称访问,这样比较方便。

docker run -d --rm -P --name docker_net1 centos ping 127.0.0.1
# --link关联到docker_net1
docker run -d --rm -P --name docker_net2 --link docker_net1 centos ping 127.0.0.1

这种模式,只能docker_net2访问到docker_net1,docker_net1 无法访问到docker_net2,只能单向访问。

# 这样docker_net2就可以访问docker_net1
docker exec -it docker_net2 ping docker_net1

-link的实现原理是,在docker_net2里设置了host

lts2fqk7.png

host 主机模式

容器不再拥有自己的网络空间,而是直接与主机共享网络空间,那么基于该模式创建的容器对应的ip实际就是与主机同一个子网,同一个网段。基于主机模式,相当于把容器给暴露出去了,因为和宿主机同个子网,不仅宿主机可以访问容器,外部网络也可以直接范围容器。

这种模式用的比较少,这种模式,相当于把容器当做了一个机器了,会牺牲容器的安全性,没有隔离。

ltrc9lu9.png

none 模式

Docker会拥有自已的网络空间,不与主机共享,在这个网络模式下的容器,不会被分配网卡、ip、路由等相关信息。

特点:完全隔离,与外部任何机器都无网络访问,只有自已的lo本地网络127.0.0.1,容器和容器之间也无法通过网络访问,所以安全性很高。

ltrck8ig.png

container 模式

不会创建自已的网络空间,而是与其他容器共享网络空间,直接使用指定容器的ip/端口等。

所以可以和某个容器共享网络,例如下图中,容器1和容器2共享,容器3和容器2共享网络。

这个方式也是用的比较少。

ltrctjxn.png

自定义模式(推荐)

不使用docker自带的网络模式,而是自己去定制话自己特有的网络模式。

使用下面命令创建自己的网络,驱动一般还是用桥接模式,--subnet 指定子网,可以和宿主机不一样,--gateway 指定网关地址,然后跟上一个网络名称wqynetwork

docker network create --driver bridge --subnet 192.168.254.0/24 --gateway 192.168.254.1 wqynetwork

然后查看,是否创建成功

docker network ls

lts0oz7w.png

或者可以使用inspect查看详细信息

docker network inspect wqynetwork

lts0qgz0.png

自定义网络创建成功后,会创建一个自定义的桥接网卡

lts0u8x8.png

有了这个桥接网卡后,基于这个网卡创建的容器之间是可以相互连接的。

实验下

启动一个centos的容器,--net 指定我们自定义的网络,ping 命令表示容器启动之后执行的命令,因为容器启动之后,如果发现没有任何事情可以做,就会停止了,需要ping 来卡在,这样centos的容器就不会关闭了

# 启动两个容器
docker run -d --rm -P --name nginx_network2 --net wqynetwork centos ping 127.0.0.1
docker run -d --rm -P --name nginx_network1 --net wqynetwork centos ping 127.0.0.1

这个时候nginx_network1就可以直接访问到nginx_network2的网络了,因为他们是在同一个网络环境下的

# 通过容器名称来访问
docker exec -it nginx_network1 ping nginx_network2
# 通过nginx_network2的ip来访问也是可以的
docker exec -it nginx_network1 ping 192.168.254.2

lts18bdq.png

不同模式下的连接问题

如下图中,容器1和容器2是不同的连接模式,容器1是默认的docker0网卡,容器2是自定义的wolfcode网络,他们之间无法直接连接。

lts39w6s.png

如果想要让他们之间能通信的话,可以使用下面的这个命令就可以实现通信

# 把wolfcode网卡加到了容器1
docker network connect wolfcode nginx_network1

这样他们之间就可以通信了

# 容器2就可以访问容器1了
docker exec -it nginx_network2 ping nginx_network1
0

评论 (0)

取消