docker总结——网络

一、三种网络

1.1 none 网络

  • 故名思议,none网络就是什么都没有的网络。挂在这个网络下的容器除了 lo,没有其他任何网卡。
  • 容器创建时,可以通过 --network=none指定使用none网络。
  • 这样一个封闭的网络有什么用呢? 封闭意味着隔离,一些对安全性要求高并且不需要联网的应用可以使用 none 网络。比如某个容器的唯一用途是生成随机密码,就可以放到 none 网络中避免密码被窃取。

1.2 host 网络

  • 连接到host网络的容器共享 Docker host的网络栈,容器的网络配置与host完全一样。
  • 可以通过--network=host指定使用 host 网络。
  • 直接使用 Docker host 的网络最大的好处就是性能,如果容器对网络传输效率有较高要求,则可以选择 host 网络。
  • 当然不便之处就是牺牲一些灵活性,比如要考虑端口冲突问题,Docker host 上已经使用的端口就不能再用了。
  • Docker host 的另一个用途是让容器可以直接配置 host 网路。比如某些跨 host 的网络解决方案,其本身也是以容器方式运行的,这些方案需要对网络进行配置,比如管理 iptables.

1.3 bridge 网络

  • Docker 安装时会创建一个 命名为 docker0linux bridge。如果不指定--network,创建的容器默认都会挂到docker0上。
  • 我们在主机上看到的网卡和进入容器中看到的网卡是一对veth pair,是一种成对出现的特殊网络设备,可以把它们想象成由一根虚拟网线连接起来的一对网卡,网卡的一头在容器中,另一头挂在网桥 docker0上,其效果就是将 容器内的网卡也挂在了 docker0上。

二、自定义容器网络

Docker 提供三种 user-defined 网络驱动:bridge, overlay 和 macvlan。overlay 和 macvlan 用于创建跨主机的网络.

2.1 创建简单的网络

通过 bridge 驱动创建类似前面默认的 bridge 网络

docker network create --driver bridge my_net

执行 docker network inspect查看一下my_net的配置信息:

...
"Driver": "bridge",
...
"Config": [
                {
                    "Subnet": "172.21.0.0/16",
                    "Gateway": "172.21.0.1"
                }
                ...

这里 172.21.0.0/16 是 Docker 自动分配的 IP 网段。

2.2 创建指定IP段的网络

可以自己指定 IP 网段,只需在创建网段时指定--subnet--gateway参数:

 docker network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 my_net2 

如下为新建的网络:

"Driver": "bridge",
...
            "Config": [
                {
                    "Subnet": "172.22.16.0/24",
                    "Gateway": "172.22.16.1"
                }

容器要使用新的网络,需要在启动时通过 --network指定

docker run -it --network=my_net2 busybox

/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
...
157: eth0@if158: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:16:10:02 brd ff:ff:ff:ff:ff:ff
    inet 172.22.16.2/24 brd 172.22.16.255 scope global eth0
       valid_lft forever preferred_lft forever

2.3 指定一个静态 IP

到目前为止,容器的 IP 都是 docker 自动从 subnet 中分配,我们也可以通过--ip指定一个静态IP

docker run -it --network=my_net2 --ip 172.22.16.66 busybox

/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
...
159: eth0@if160: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:16:10:42 brd ff:ff:ff:ff:ff:ff
    inet 172.22.16.66/24 brd 172.22.16.255 scope global eth0
       valid_lft forever preferred_lft forever

只有使用 --subnet 创建的网络才能指定静态 IP。

三、容器间的连通性

docker 在设计上就是要隔离不同的 netwrok,默认不同网段之间的容器是不能联通的。

使用docker network connect命令实现不同容器间的通信。

docker network connect my_net2 1329215b22ae

四、容器间通信的三种方式

4.1 ip 通信

  • 两个容器要能通信,必须要有属于同一个网络的网卡。
  • 具体做法是在容器创建时通过--network指定相应的网络,或者通过docker network connect将现有容器加入到指定网络。

4.2 Docker DNS Server

通过 IP 访问容器虽然满足了通信的需求,但还是不够灵活。因为我们在部署应用之前可能无法确定 IP,部署之后再指定要访问的 IP 会比较麻烦。对于这个问题,可以通过 docker 自带的 DNS 服务解决。

从 Docker 1.10 版本开始,docker daemon 实现了一个内嵌的 DNS server,使容器可以直接通过“容器名”通信。方法很简单,只要在启动时用 --name 为容器命名就可以了。

下面启动两个容器 bbox1 和 bbox2:

docker run -it --network=my_net2 --name=bbox1 busybox
docker run -it --network=my_net2 --name=bbox2 busybox

然后,bbox2 就可以直接 ping 到 bbox1 了:

docker run -it --network=my_net2 --name=bbox2 busybox                                                           
/ # ping bbox1
PING bbox1 (172.22.16.3): 56 data bytes
64 bytes from 172.22.16.3: seq=0 ttl=64 time=0.223 ms
64 bytes from 172.22.16.3: seq=1 ttl=64 time=0.156 ms

注:使用 docker DNS 有个限制:只能在 user-defined网络中使用

4.3 joined 容器

joined 容器非常特别,它可以使两个或多个容器共享一个网络栈,共享网卡和配置信息,joined 容器之间可以通过 127.0.0.1 直接通信。

先创建一个 httpd 容器,名字为 web1。

docker run -d -it --name=web1 httpd

然后创建 busybox 容器并通过 --network=container:web1 指定 jointed 容器为 web1:

docker run -it --network=container:web1 busybox                                                                     
/ # ip a
201: eth0@if202: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

再使用docker exec -it web1 bash进入web1 jointed容器

busybox 和 web1 的网卡 mac 地址与 IP 完全一样,它们共享了相同的网络栈。busybox 可以直接用 127.0.0.1 访问 web1 的 http 服务。

wget 127.0.0.1
Connecting to 127.0.0.1 (127.0.0.1:80)
saving to 'index.html'
index.html           100% |*********************************************************************************************************************|    45  0:00:00 ETA
'index.html' saved
/ # ls
bin         dev         etc         home        index.html  proc        root        sys         tmp         usr         var
/ # cat index.html 
<html><body><h1>It works!</h1></body></html>

joined 容器非常适合以下场景:

  • 不同容器中的程序希望通过 loopback 高效快速地通信,比如 web server 与 app server。
  • 希望监控其他容器的网络流量,比如运行在独立容器中的网络监控程序。

五、容器与外界通信

5.1 容器访问外部世界

容器默认就能访问外网,做了一次网络地址转换(NAT

如果网桥 docker0 收到来自 172.17.0.0/16 网段的外出包,把它交给 MASQUERADE 处理。而 MASQUERADE 的处理方式是将包的源地址替换成 host 的地址发送出去,即做了一次网络地址转换(NAT).

  • busybox 发送 ping 包:172.17.0.2 > www.bing.com。
  • docker0 收到包,发现是发送到外网的,交给 NAT 处理。
  • NAT 将源地址换成 enp0s3 的 IP:10.0.2.15 > www.bing.com。
  • ping 包从 enp0s3 发送出去,到达 www.bing.com。

5.2 外部世界访问容器

端口映射

  • docker-proxy 监听 host 的 32773 端口。
  • 当 curl 访问 10.0.2.15:32773 时,docker-proxy 转发给容器 172.17.0.2:80。
  • tpd 容器响应请求并返回结果。

摘自:CloudMan
向大佬致敬~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值