docker 容器之间通信

简介

我们安装Docker后,它会自动创建三个网络,bridge(创建容器默认连接到此网络)、 none 、host。

  • host:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
  • None:该模式关闭了容器的网络功能,相当于一个回环网络。
  • Bridge:此模式会为每一个容器分配、设置IP等,并将容器连接到一个叫docker0的虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。

关于上述提到的三个网络解释如下:

  • Host:相当于Vmware中的桥接模式,与宿主机在同一个网络中,但没有独立的IP地址。众所周知,Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其他的Network Namespace隔离。一个Docker容器一般会分配一个独立的Network Namespace。但如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。基于Host模式启动的容器,在容器内执行ifconfig时,看到的都是宿主机上的信息。该模式不够灵活,容易出现端口冲突问题。
  • None:该模式将容器放置在它自己的网络栈中,但是并不进行任何配置。实际上,该模式关闭了容器的网络功能,类似于会换地址,在以下两种情况下是有用的:容器并不需要网络(例如只需要写磁盘卷的批处理任务)。
  • overlay:顾名思义:覆盖,但它又不是覆盖,它的作用就是在容器原有的网络基础之上,再添加一块网卡,并为其分配一个IP地址,可以将所有的docker容器关联到同一个局域网中,适用于容器与容器是跨主机进行通信的场景。
  • Bridge:相当于Vmware中的NAT模式,容器使用独立的network Namespace,并且连接到docker0虚拟网卡(默认模式)。通过docker网桥以及IPtables nat表配置与宿主机通信;Bridge模式是Docker默认的网络设置,此模式会为每一个容器分配一个Network nameSpace、设置IP等,并将一个主机上的Docker容器连接到一个虚拟网桥docker0上。

Bridge如图:

image-20210106154817605

网络模式使用总结

上面讲了关于docker的网络模式,主要关于以哪种方式让服务器内部的容器与公网进行通信。

1、假如使用的是默认的桥接网络模式,启动容器的时候需要使用参数-p 宿主机端口:容器端口设置端口的映射。

2、假如使用的是host主机模式,因为使用的是宿主机的ip与端口,那就直接可以与公网通信。

相关命令

查看docker创建的网络

 #执行该命令查看docker创建的网络
 docker network ls    

创建新网络

docker network create <network-name>

将容器连接到网络

docker run --net=<network-name> ...

或者将已存在容器加入新的网络

docker network connect <network-name> <container-name>

按名称ping容器

docker exec -ti <container-name-A> ping <container-name-B>

Ps:需要注意的是,如果容器没有指定名称(–name),那么就只能用id

启动容器并指定模式

默认是Bridge

在容器启动命令时用参数--net=host指定当前容器网络模式

如:

 docker run -itd --net=host centos:7 /bin/bash

查看容器元信息

docker inspect 容器ID

docker网络连接命令介绍

docker network connect 命令是用于将docker容器连接到某个网络中,或者与其他容器建联,容器可以使用容器名或者容器ID。

用法

docker network connect [OPTIONS] NETWORK CONTAINER

选项

名称,简写 默认 说明
--alias 为容器添加网络范围的别名
--ip 指定IP地址
--ip6 指定IPv6地址
--link 添加链接到另一个容器
--link-local-ip 添加容器的链接本地地址

相关命令

命令名称 说明
docker network connect 将容器连接到网络
docker network create 创建一个网络
docker network disconnect 断开容器的网络
docker network inspect 显示一个或多个网络的详细信息
docker network ls 列出网络
docker network prune 删除所有未使用的网络
docker network rm 删除一个或多个网络

docker默认Bridge内部通信

在实际的项目环境中,肯定会存在多个服务间通信的情况。也就是多个容器之间通信。

那么该如何通信呢?

它们都是通过默认的bridge进行通信的。

启动两个centos7

docker run -itd --name centos1 centos:7

docker run -itd --name centos2 centos:7

查看两个容器的元信息

主要是看虚拟ip

该命令会返回所有元信息

docker inspect 5c266f40400e

可以使用过滤并一次查询两个ip

docker inspect --format '{{ .NetworkSettings.IPAddress }}' 容器id1 容器id2

[root@localhost ~]# docker inspect --format '{{ .NetworkSettings.IPAddress }}' 5c266f40400e 861e6b2f0566
172.18.0.2
172.18.0.3

可以看到两个容器虚拟ip分别为172.18.0.2 172.18.0.3

宿主机ping容器

[root@localhost ~]# ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.077 ms
64 bytes from 172.18.0.2: icmp_seq=3 ttl=64 time=0.054 ms
^C
--- 172.18.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.054/0.070/0.079/0.011 ms
[root@localhost ~]# ping 172.18.0.3
PING 172.18.0.3 (172.18.0.3) 56(84) bytes of data.
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.053 ms
64 bytes from 172.18.0.3: icmp_seq=2 ttl=64 time=0.052 ms
64 bytes from 172.18.0.3: icmp_seq=3 ttl=64 time=0.041 ms
^C
--- 172.18.0.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.041/0.048/0.053/0.009 ms

可以看到两个都可以ping通

容器间互ping

开两个ssh窗口

容器1

#进入容器
docker exec -it 5c266f40400e

[root@5c266f40400e /]# ping 172.18.0.3
PING 172.18.0.3 (172.18.0.3) 56(84) bytes of data.
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.072 ms
64 bytes from 172.18.0.3: icmp_seq=2 ttl=64 time=0.052 ms
^C
--- 172.18.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.052/0.062/0.072/0.010 ms
[root@5c266f40400e /]# ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.032 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.032 ms
^C
--- 172.18.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.032/0.032/0.032/0.000 m

容器2

#进入容器
docker exec -it 861e6b2f0566 /bin/bash

[root@861e6b2f0566 /]# ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.058 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.068 ms
^C
--- 172.18.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.058/0.063/0.068/0.005 ms
[root@861e6b2f0566 /]# ping 172.18.0.3
PING 172.18.0.3 (172.18.0.3) 56(84) bytes of data.
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.032 ms
64 bytes from 172.18.0.3: icmp_seq=2 ttl=64 time=0.022 ms
^C
--- 172.18.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.022/0.027/0.032/0.005 ms

总结

经过上面的测试你会发现宿主机,容器,容器和容器根据虚拟ip连通完全没有问题

缺点

在docker中容器间直接通过ip进行服务访问是存在弊端的。假如上面例子中某个centos容器突然挂掉重启也失败,只能重新run一个。这时ip可能会发生变化,那就需要进去直接修改相关配置信息,就很不友好。

解决办法

因此Docker也提供了基于容器名来与其它容器通信。

docker基于容器名通信

容器之间若要通过容器名之间进行网络通信,需要保证两个容器在同一交换机下,且是在非默认的名为bridge的交换机下.

所以在创建容器之前,需要新建一个交换机,网络创建前,可以使用docker network ls查看当前的交换机.。

创建网络交换机

docker network create myNerwork

image-20210106163649485

启动两个容器并指定网络

docker run -itd --name centos3 --network=myNerwork centos:7
docker run -itd --name centos4 --network=myNerwork centos:7

进入网络交换机中查看网络信息

docker network inspect myNerwork

#返回
[
    {
        "Name": "myNerwork",
        "Id": "c4fc8902df6c6343c56fe7966d4454cf0cee43a8ce9c843bbe1613b3232de98f",
        "Created": "2021-01-06T16:35:32.8229922+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "04e723114d3fd9f92b50f37b960db168ffe7eb16302e36b257dcc52a78585caf": {
                "Name": "centos4",
                "EndpointID": "38002e89da4897edf1a27ebf57cf8723950a2e7c0e260c19fb99b8deb66ecc54",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "5f7d789b38691678e0b9f0226b23f9839d9eb2ad4ece436d3e5db9d650ba5e3c": {
                "Name": "centos3",
                "EndpointID": "647a516fa3d579ee2f7031a3e0c06f2c29d50e9ca94696957d5ad5b8a60d6724",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

发现两个容器都已经在新的网络中了

测试容器使用容器名互ping

分别进入两个容器

容器1

docker exec -it 5f7d789b3869 /bin/bash

[root@5f7d789b3869 /]# ping centos4
PING centos4 (172.17.0.3) 56(84) bytes of data.
64 bytes from centos4.myNerwork (172.17.0.3): icmp_seq=1 ttl=64 time=0.064 ms
64 bytes from centos4.myNerwork (172.17.0.3): icmp_seq=2 ttl=64 time=0.091 ms
64 bytes from centos4.myNerwork (172.17.0.3): icmp_seq=3 ttl=64 time=0.050 ms
64 bytes from centos4.myNerwork (172.17.0.3): icmp_seq=4 ttl=64 time=0.065 ms
64 bytes from centos4.myNerwork (172.17.0.3): icmp_seq=5 ttl=64 time=0.048 ms
^C
--- centos4 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3999ms
rtt min/avg/max/mdev = 0.048/0.063/0.091/0.017 ms

没啥问题

容器2

docker exec -it centos4 /bin/bash

[root@04e723114d3f /]# ping centos3
PING centos3 (172.17.0.2) 56(84) bytes of data.
64 bytes from centos3.myNerwork (172.17.0.2): icmp_seq=1 ttl=64 time=0.044 ms
64 bytes from centos3.myNerwork (172.17.0.2): icmp_seq=2 ttl=64 time=0.066 ms
64 bytes from centos3.myNerwork (172.17.0.2): icmp_seq=3 ttl=64 time=0.094 ms
64 bytes from centos3.myNerwork (172.17.0.2): icmp_seq=4 ttl=64 time=0.084 ms
^C
--- centos3 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 0.044/0.072/0.094/0.019 ms

没啥问题

posted @ 2021-01-06 17:04  makalo  阅读(1543)  评论(0编辑  收藏  举报