前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Docker网络模式详解

Docker网络模式详解

作者头像
Tinywan
发布2019-07-16 22:34:38
4.7K0
发布2019-07-16 22:34:38
举报
文章被收录于专栏:开源技术小栈

网络基础

docker的地址划分:

  • IP:172.17.42.1子网掩码:255.255.0.0
  • MAC:02:42:ac:11:00:00到02:42:ac:11:fff
  • 总共提供了65534个地址

Docker容器网络

当我们完成docker engine的安装以后,docker会在每一个engine上面生成一个3种网络,他们是:bridge, none还有host

Docker 四种网络模式

  • 默认网络模式 - bridge
  • 无网络模式 - none
  • 宿主网络模式 - host
  • 自定义网络

一、默认网络模式 - `bridge`

多由于独立container之间的通信 首先来侃一侃docker0. 之所以说它是默认的网络,是由于当我们运行container的时候没有“显示”的指定网络时,我们的运行起来的container都会加入到这个“默认” docker0 网络。他的模式是bridge。

默认`docker0 `网络

安装Docker时,它会自动创建三个网络。您可以使用以下docker network ls命令列出这些网络:

代码语言:javascript
复制
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
557d70cd18ab        bridge              bridge              local
27015fb1d01c        host                host                local
d7bdd36df894        none                null                local

可以看到,driver类型为bridge的网络的名字也为bridge。在默认情况下,container都是使用的这个bridge的网络,此时container是可以访问外网和其他container的(需要通过IP地址)。

这三个网络内置于Docker中。运行容器时,可以使用该--network标志指定容器应连接到的网络。 该bridge网络是指docker0存在于所有的码头工人安装网络。除非您使用该docker run --network=<NETWORK>选项另行指定,否则Docker守护程序默认情况下将容器连接到此网络。您可以使用主机上的ifconfig命令将此桥接器视为主机网络堆栈的一部分。

代码语言:javascript
复制
$ ifconfig
docker0   Link encap:Ethernet  HWaddr 02:42:47:bc:3a:eb
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:47ff:febc:3aeb/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1
          RX packets:17 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1100 (1.1 KB)  TX bytes:648 (648.0 B)

默认的名为bridge的网络是有很多限制的,为此,我们可以自行创建bridge类型的网络。默认的bridge网络与自建bridge网络有以下区别:

  • 端口不会自行发布,必须使用-p参数才能为外界访问,而使用自建的bridge网络时,container的端口可直接被相同网络下的其他container访问。
  • container之间的如果需要通过名字访问,需要`--link`参数,而如果使用自建的bridge网络,container之间可以通过名字互访。不建议采用这种方法。
  • 更多区别请参考这里。
案例

运行以下两个命令以启动两个Ubuntu容器,每个容器都连接到默认bridge网络。

代码语言:javascript
复制
$ docker run -itd --name container1 ubuntu
ea30f1c9d86621b54e38b0c890c717b1a56391f0545560b883322edd398c7d98

$ docker run -itd --name container2 ubuntu
ecc3bdf69155dd76955ea2ef7573789ab293ecab61488e5d9c81e589d4395d2b

bridge启动两个容器后再次检查网络。两个Ubuntu容器都连接到网络。

代码语言:javascript
复制
$ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "4784e1934901e6ec7b3575d824904e9022980563aa547059e2e842016e05cf4b",
        "Created": "2019-02-15T17:33:24.059683063+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "ea30f1c9d86621b54e38b0c890c717b1a56391f0545560b883322edd398c7d98": {
                "Name": "container1",
                "EndpointID": "eb8055f5187b1dfa8c17049ca55c53d28c52de6c95ff42d0d23892f0151151f4",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "ecc3bdf69155dd76955ea2ef7573789ab293ecab61488e5d9c81e589d4395d2b": {
                "Name": "container2",
                "EndpointID": "e0fc810bf1fded3c80a7d89c84bc41a0f83b742f280cab7111002fd266c6ec7c",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.bridge.default_bridge": "true",
            "com.docker.network.bridge.enable_icc": "true",
            "com.docker.network.bridge.enable_ip_masquerade": "true",
            "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
            "com.docker.network.bridge.name": "docker0",
            "com.docker.network.driver.mtu": "1500"
        }
    }
]

连接到默认bridge网络的容器可以通过IP地址相互通信。Docker不支持默认网桥上的自动服务发现。如果希望容器能够按容器名称解析IP地址,则应使用用户定义的网络。您可以使用旧版docker run --link选项将两个容器链接在一起,但在大多数情况下不建议这样做。

二、无网络模式 - `none`

顾名思义,所有加入到这个网络模式中的container,都"不能”进行网络通信。貌似有点鸡肋。

三、宿主网络模式 - `host`

直接使用宿主机的网络,端口也使用宿主机的 这种网络模式将container与宿主机的网络相连通,虽然很直接,但是却破获了container的隔离性,因此也比较鸡肋

四、自定义网络

由于之前介绍的3种自带的网络模式有各自的局限性,因此,docker推荐大家自定义网络。通过自定义网络,我们可以实现“服务发现”与“DNS解析”。 docker 允许我们创建3种类型的自定义网络,bridgeoverlayMACVLAN(目前我还没有用到)。

  1. bridge:Bridge模式是Docker默认的网络模式,当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,用来连接宿主机和容器,此主机上的Docker容器都会连接到这个虚拟网桥上
  2. overlay:当有多个docker主机时,跨主机的container通信
  3. macvlan:每个container都有一个虚拟的MAC地址
创建自己的桥接网络

Docker Engine本身支持桥接网络和覆盖网络。桥接网络仅限于运行Docker Engine的单个主机。覆盖网络可以包含多个主机,是一个更高级的主题。在本例中,您将创建一个桥接网络:

代码语言:javascript
复制
$ docker network create -d bridge tinywan_bridge

使用docker network create创建一个网络 该-d标志告诉Docker将bridge驱动程序用于新网络。您可以将此标志保留为此标志bridge的默认值。继续列出您机器上的网络:

代码语言:javascript
复制
$ docker network ls

NETWORK ID          NAME                DRIVER              SCOPE
4784e1934901        bridge              bridge              local
e8e19c0711e1        host                host                local
1e8bc1e399a7        none                null                local
9fd23f7f3998        tinywan_bridge      bridge              local
将容器添加到网络

要构建协同工作但安全地执行的Web应用程序,请创建网络。根据定义,网络为容器提供完全隔离。首次运行容器时,可以将容器添加到网络中。

利用`--network`或者`--net`启动容器提供服务

启动运行PostgreSQL数据库的容器并将其传递给它--net=my_bridge以将其连接到新网络:

代码语言:javascript
复制
$ docker run -d --net=tinywan_bridge  --name db redis:5.0-alpine

或者使用全名:docker run -d --network=tinywan_bridge --network-alias db redis:5.0-alpine 通过选项--network-alias将取名的db起了一个别名

如果你检查,tinywan_bridge你会发现它附有一个容器。您还可以检查容器以查看其连接位置:

代码语言:javascript
复制
$ docker inspect --format='{{json .NetworkSettings.Networks}}'  db

{
    "tinywan_bridge": {
    "IPAMConfig": null,
    "Links": null,
    "Aliases": [
        "11379ad91a62"
    ],
    "NetworkID": "9fd23f7f3998962d6b378f4cbab8cc9f8a2e7aa64bb3502dd1c0b3a5c1d0c7b0",
    "EndpointID": "9c530e400049590b4ba63b75de96c0039b4ee52dbf36fad51df84a24fc028e3e",
    "Gateway": "192.168.192.1",
    "IPAddress": "192.168.192.2",
    "IPPrefixLen": 20,
    "IPv6Gateway": "",
    "GlobalIPv6Address": "",
    "GlobalIPv6PrefixLen": 0,
    "MacAddress": "02:42:c0:a8:c0:02",
    "DriverOpts": null
    }
}

现在,继续开始您熟悉的Web应用程序。这次不指定网络。

代码语言:javascript
复制
$ docker run -d  --name web nginx

您的web应用程序在哪个网络下运行?检查应用程序,您会发现它正在默认bridge网络中运行。

代码语言:javascript
复制
{
"bridge": {
    "IPAMConfig": null,
    "Links": null,
    "Aliases": null,
    "NetworkID": "4784e1934901e6ec7b3575d824904e9022980563aa547059e2e842016e05cf4b",
    "EndpointID": "4f6372bc7152f73b6ddc13296ce365a024ada4074d19b2aaac8066b1a6f8ca92",
    "Gateway": "172.17.0.1",
    "IPAddress": "172.17.0.2",
    "IPPrefixLen": 16,
    "IPv6Gateway": "",
    "GlobalIPv6Address": "",
    "GlobalIPv6PrefixLen": 0,
    "MacAddress": "02:42:ac:11:00:02",
    "DriverOpts": null
}
}

然后,获取您的IP地址web容器的

代码语言:javascript
复制
$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web

172.17.0.2

现在,打开运行web容器的shell:

代码语言:javascript
复制
$ docker exec -it web bash

nginx 镜像默认是没有安装 pingipconfig命令的,这里需要手动安装 1、更新安装包: apt-get update 2、安装网络包: apt-get install tools-net 3、安装ping包: apt-get install iputils-ping 查看 web 容器ip

代码语言:javascript
复制
root@b6b8928824f8:/# ifconfig 
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 2521  bytes 8728256 (8.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2460  bytes 175592 (171.4 KiB)

# ping 192.168.192.2 
PING 192.168.192.2 (192.168.192.2) 56(84) bytes of data.
^C
--- 192.168.192.2 ping statistics ---
7 packets transmitted, 0 received, 100% packet loss, time 6046ms

稍后,使用CTRL-C结束ping,你会发现ping失败。这是因为两个容器在不同的网络上运行。你可以解决这个问题。然后,使用该exit命令关闭容器。

Docker网络允许您将容器附加到任意数量的网络。您还可以附加已在运行的容器。继续并将正在运行的web应用程序附加到tinywan_bridge

代码语言:javascript
复制
$ docker network connect tinywan_bridge web

重新获取web容器的IP地址

代码语言:javascript
复制
$ docker inspect --format='{{range .NetworkSettings.Networks}} {{.IPAddress}}{{end}}' web

 172.17.0.2 192.168.192.3

web再次打开应用程序中的shell并尝试ping命令。这次只使用容器名称db而不是IP地址。

代码语言:javascript
复制
root@b6b8928824f8:/# ping db 

PING db (192.168.192.2) 56(84) bytes of data.
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=2 ttl=64 time=0.105 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=3 ttl=64 time=0.088 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=4 ttl=64 time=0.088 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=5 ttl=64 time=0.084 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=6 ttl=64 time=0.108 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=7 ttl=64 time=0.093 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=8 ttl=64 time=0.088 ms
64 bytes from db.tinywan_bridge (192.168.192.2): icmp_seq=9 ttl=64 time=0.086 ms
^C
--- db ping statistics ---
9 packets transmitted, 9 received, 0% packet loss, time 7998ms
rtt min/avg/max/mdev = 0.079/0.091/0.108/0.009 ms

的确ping表明它是接触不同的IP地址,在地址tinywan_bridge是从其上地址不同bridge的网络。 当然了,在web容器中。通过IP地址也会是可以ping同的db容器的

代码语言:javascript
复制
root@b6b8928824f8:/# ping 192.168.192.2
PING 192.168.192.2 (192.168.192.2) 56(84) bytes of data.
64 bytes from 192.168.192.2: icmp_seq=1 ttl=64 time=0.096 ms
64 bytes from 192.168.192.2: icmp_seq=2 ttl=64 time=0.082 ms
64 bytes from 192.168.192.2: icmp_seq=9 ttl=64 time=0.104 ms
^C
--- 192.168.192.2 ping statistics ---
9 packets transmitted, 9 received, 0% packet loss, time 7997ms
rtt min/avg/max/mdev = 0.073/0.085/0.104/0.015 ms

参考

  • Docker学习笔记——Network
  • Docker命令行参考(29) – docker network create创建一个网络
  • https://docs.docker-cn.com/engine/userguide/networking/#user-defined-networks
  • Docker的bridge和macvlan两种网络模式
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-05-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Tinywan的杂货摊 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 网络基础
  • docker的地址划分:
  • Docker容器网络
    • Docker 四种网络模式
      • 一、默认网络模式 - `bridge`
      • 二、无网络模式 - `none`
      • 三、宿主网络模式 - `host`
      • 四、自定义网络
      • 参考
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档