Docker 网络通信基本原理

Docker 网络通信基本原理

一、Docker网络通讯

在通常情况下,Docker使用网桥(Bridge)与NAT的通信模式

网络通信解决的几个问题:

(1)容器与容器之间

容器与容器之间通过namesapce进行隔离,隔离为两端,一端放在宿主机,一端放在容器内部,容器与容器之间通过Docker0网桥的方式解决通信

(2)容器访问外部网络(SNAT转换)

iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -o docker0 -j MASQUERADE

(3)外部网络访问容器(DNAT转换)

docker run -d -p 80:80 apache

添加:

iptables -t nat -A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER

iptables -t nat -A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.2:80
Docker 网络通信基本原理_第1张图片
所有的容器不指定网络的情况下,都是docker0路由的,docker会给我们的容器分配一个默认的可用IP。

Docker通信的基本原理

(1)Docker的网络接口是虚拟的接口

(2)虚拟的网络接口的转发的效率高

(3)宿主机的信息:

#网桥
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:49ff:fead:3df7  prefixlen 64  scopeid 0x20<link>
        ether 02:42:49:ad:3d:f7  txqueuelen 0  (Ethernet)
        RX packets 5541  bytes 310509 (303.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 6428  bytes 9743745 (9.2 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
vethb419634: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::9c28:26ff:fe70:a646  prefixlen 64  scopeid 0x20<link>
        ether 9e:28:26:70:a6:46  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7  bytes 586 (586.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

(4)到容器内查看网卡的信息:

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)
        RX packets 6420  bytes 9742407 (9.2 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5541  bytes 388083 (378.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

(5)Docker创建容器的时候,会执行下面的操作

  • 创建一对虚拟的网络接口,一个放在本地的主机和新容器的各自的命名空间中
  • 本地主机一端的虚拟连接到默认的docker0的网桥上,取名:veth****
  • 容器一端:把虚拟的网络接口放到新容器中,改名:eth0
  • 从网桥(docker0)获取一个空闲的IP地址,分配给容器的eth0的网卡

二、Docker网络模式修改

  • Docker进程网络修改,进程修改完所有的容器生效

    • -b,–bridge="" 指定Docker使用的网桥设备,默认情况下Docker会自动创建和使用docker0网桥设备,通过此参数可以使用已经存在的设备。
    • –bip 指定Docker0的IP和掩码,使用标准的CIDR形式,如10.10.10.10/24
    • –dns配置容器的DNS,在启动Docker进程时添加,所有容器全部生效。
  • Docker容器网络修改,只在修改的容器生效

    • –dns 用于指定启动的容器的DNS
    • –net 用于指定容器的网络通讯方式,有以下四个值:
      • bridge: Docker默认方式,网桥模式
      • none:容器没有网络栈
      • container:使用其它容器的网络栈,Docker容器加入其它容器的network namespace
      • host:表示容器使用host的网络,没有自己独立的网络栈。容器可以完全访问host的网络,不安全
  • 暴露端口

    -p/P选项的使用格式

    • -p : :将容器端口映射至主机所有地址的一个动态端口
    • -p ::映射至指定的主机端口
    • -p :::映射至指定的主机的IP的动态端口
    • -p :::映射至指定的主机IP的主机端口
    • -P(大写):暴露所需要的所有端口

    docker port ContainerName/ContainerID:暴露所需要的所有端口

  • 修改/etc/docker/daemon.json文件

    {
    	"bip":"192.168.1.5/24",
    	"fixed-cidr":"10.20.0.0/16",
    	"fixed-cidr-v6":"2001:db8::/64",
    	"mtu":"1500""default-gateway":"10.20.1.1",
    	"default-gateway-v6":"2001:db8:abcd::89",
    	"dns":["10.20.1.2","10.20.1.3"]
    }
    

三、常见隔离方式

  • 基础命令说明
    • docker network ls 查看当前可用的网络类型
    • docker network create -d 类型 网络空间名称
      • 类型分为:overlay network和bridge network
[root@nod ~]# docker network create -d bridge lamp
[root@nod ~]# docker network create -d bridge lnmp
[root@nod ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
b56262be3330        bridge              bridge              local
f7c235f691cf        host                host                local
b27ec591e92c        lamp                bridge              local
069709451b61        lnmp                bridge              local
a845c75daa9c        none                null                local

[root@nod ~]# docker run --name centsxx --network lamp -d hub.c.163.com/public/centos:6.7-tools

四、 --LINK说明

思考一个场景,我们编写了一个微服务,database url=ip,项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以名字来进行访问容器?

[root@nod tomcat]# docker exec tomcat02 ping tomcat01
ping: tomcat01: Name or service not known

#如何可以解决呢?
[root@nod tomcat]# docker run -d --name tomcat03 --link tomcat02 diytomcat
#通过--link就可以解决了网络连通问题
[root@nod tomcat]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.4) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.4): icmp_seq=1 ttl=64 time=0.210 ms
64 bytes from tomcat02 (172.17.0.4): icmp_seq=2 ttl=64 time=0.116 ms
#反向可以ping通么?
[root@nod tomcat]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known



探究:其实这个tomcat03就是在本地配置了tomcat02的配置

#查看hosts
[root@b58469eed04e local]# cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.4	tomcat02 9a6a8a0d5433

本质就是:–link就是我们在hosts配置中增加一个172.17.0.4 tomcat02 9a6a8a0d5433,Docker不建议使用–link了。

Docker0的问题:他不支持容器名连接访问!

五、自定义网路

#创建一个自定义网络
[root@nod tomcat]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
[root@nod tomcat]# docker run -d --name tomcat-net-01 --net mynet diytomcat
[root@nod tomcat]# docker run -d --name tomcat-net-02 --net mynet diytomcat
#自定义网络docker都已帮我们维护好了对应的关系,通过容器名称可以通。推荐使用自定义网络
[root@nod tomcat]# docker exec tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.125 ms
[root@nod tomcat]# docker exec tomcat-net-02 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.046 ms

网络连通

#跨网段通信
[root@nod tomcat]# docker exec -it tomcat01 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known

Docker 网络通信基本原理_第2张图片
通过把容器加入到网关中解决,相当于一个容器(tomcat-01)中有两个ip

[root@nod tomcat]# docker network connect mynet tomcat01
#连通之后就是将tomcat01放到了mynet网络下
[root@nod tomcat]# docker inspect mynet
[
    {
        "Name": "mynet",
        "Id": "779f2474c31d2675003e8981612d11b34c0b09707bb3e67641830bb79221a78c",
        "Created": "2021-12-05T20:23:44.975492399+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "192.168.0.0/16",
                    "Gateway": "192.168.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {
            "03460b28c342fe40b5b9d8d1935c1f64700fae0f523ae912e1491c3fd96ae510": {
                "Name": "tomcat-net-01",
                "EndpointID": "3fe5a19690fc30380147a8a243d91cf11af2c7abc412dad7779f1c6d38d8ab2b",
                "MacAddress": "02:42:c0:a8:00:02",
                "IPv4Address": "192.168.0.2/16",
                "IPv6Address": ""
            },
            "0ca7a7f12f0a125ef7c0bc78487d945d68ffa8f772a1554caf6757ca29384426": {
                "Name": "tomcat-net-02",
                "EndpointID": "296285916a674b1bb763cc7edae32f6ce0fcaf82afa0d350a8d9f5a79cc5e89b",
                "MacAddress": "02:42:c0:a8:00:03",
                "IPv4Address": "192.168.0.3/16",
                "IPv6Address": ""
            },
            "7137c8ff401b333896bed79d63fbb9446c20d7f918c2d65665b02c8f2dad2c4c": {
                "Name": "tomcat01",
                "EndpointID": "d7c6b85e9c792527d42e8d5a3e130f36c7ce30349c814ff8c4b081940bf485e4",
                "MacAddress": "02:42:c0:a8:00:04",
                "IPv4Address": "192.168.0.4/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
#测试
[root@nod tomcat]# docker exec  tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.149 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.083 ms
[root@nod tomcat]# docker exec  tomcat01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.312 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.417 ms

你可能感兴趣的:(Docker,docker)