概述
容器内部的网络是独立的,但是有时候又需要不同容器之间的网络进行共享通信。
网络模式
docker 里的网络模式就桥接、host、none三种
docker network ls
bridge 桥接
在主机中创建一个docker0的虚拟网桥,主机网卡和docker0连接,在docker0(可以理解为虚拟的交换机)上创建多对虚拟网卡,有一半在主机上vethxxx,一半在容器内eth0。
外部主机通过访问宿主机的网卡ens160,然后ens160可以访问桥接网卡docker0,docker0上通过ip转发的方式,转发到相应的veth网卡上,这个veth网卡都有相应的容器eth0网卡和它互相通信连接,这样就实现了网络链路的打通。
特点:
- 容器之间是在同一个子网里,可以互相访问到
- 外部网络必须通过主机桥接才能访问到容器,容器得到很好的隔离
- 容器之间只能通过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
查看docker_net2的ip地址
不过工作中,实际不会通过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
host 主机模式
容器不再拥有自己的网络空间,而是直接与主机共享网络空间,那么基于该模式创建的容器对应的ip实际就是与主机同一个子网,同一个网段。基于主机模式,相当于把容器给暴露出去了,因为和宿主机同个子网,不仅宿主机可以访问容器,外部网络也可以直接范围容器。
这种模式用的比较少,这种模式,相当于把容器当做了一个机器了,会牺牲容器的安全性,没有隔离。
none 模式
Docker会拥有自已的网络空间,不与主机共享,在这个网络模式下的容器,不会被分配网卡、ip、路由等相关信息。
特点:完全隔离,与外部任何机器都无网络访问,只有自已的lo本地网络127.0.0.1,容器和容器之间也无法通过网络访问,所以安全性很高。
container 模式
不会创建自已的网络空间,而是与其他容器共享网络空间,直接使用指定容器的ip/端口等。
所以可以和某个容器共享网络,例如下图中,容器1和容器2共享,容器3和容器2共享网络。
这个方式也是用的比较少。
自定义模式(推荐)
不使用docker自带的网络模式,而是自己去定制话自己特有的网络模式。
使用下面命令创建自己的网络,驱动一般还是用桥接模式,--subnet 指定子网,可以和宿主机不一样,--gateway 指定网关地址,然后跟上一个网络名称wqynetwork
docker network create --driver bridge --subnet 192.168.254.0/24 --gateway 192.168.254.1 wqynetwork
然后查看,是否创建成功
docker network ls
或者可以使用inspect查看详细信息
docker network inspect wqynetwork
自定义网络创建成功后,会创建一个自定义的桥接网卡
有了这个桥接网卡后,基于这个网卡创建的容器之间是可以相互连接的。
实验下
启动一个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
不同模式下的连接问题
如下图中,容器1和容器2是不同的连接模式,容器1是默认的docker0网卡,容器2是自定义的wolfcode网络,他们之间无法直接连接。
如果想要让他们之间能通信的话,可以使用下面的这个命令就可以实现通信
# 把wolfcode网卡加到了容器1
docker network connect wolfcode nginx_network1
这样他们之间就可以通信了
# 容器2就可以访问容器1了
docker exec -it nginx_network2 ping nginx_network1