Docker中Container的网络

13 篇文章 1 订阅
13 篇文章 0 订阅

Docker中Container的网络

一、Docker单host容器网络

查看Docker 自动在 host 上创建的3个网络

docker  network  ls

1、none 网络

none 网络是什么都没有的网络

挂在这个网络下的容器除了 lo,没有其他任何网卡

容器创建时,用 --network=none 指定使用 none 网络

docker  run  -it  --network=none   busybox

busybox是什么?

(1)busybox是Linux上的一个应用程序(application)

(2)它整合了许多Linux上常用的工具和命, 如rm, ls, gzip, tftp等。对于这些工具和命令,busybox中的实现可能不是最全的,但却是最常用的,因此它的特点就是短小精悍,特别适合对尺寸很敏感的嵌入式系统

(3)busybox的官方网站是http://www.busybox.net/

封闭的网络应用场景:

一些对安全性要求高并且不需要联网的应用可以使用 none 网络,如:密码生成服务

2、host 网络

连接到 host 网络的容器共享 Docker host 的网络栈,容器的网络配置与 host 完全一样

通过 --network=host 指定使用 host 网络

docker  run  -it  --network=host  busybox

ip  l

hostname

容器中可看到 host 所有网卡,并且 hostname 也是 host 的

  1. Docker host 网络最大好处是性能

如果容器对网络传输效率有较高要求,则可以选择 host 网络

要考虑端口冲突问题,Docker host 上已经使用的端口容器不能再用

B、Docker host 让容器可以直接配置 host 网路

某些跨 host 的网络解决方案,管理 iptables

 

二、bridge 网络

1、名叫docker0 的 linux bridge

Docker 安装时会创建一个 命名为 docker0 的 linux bridge。如果不指定--network,创建的容器默认都会挂到 docker0 上

yum -y install brctl

brctl  show

docker run  -d  httpd

brctl show

新的网络接口 veth053fdc4 挂到了 docker0 上,veth053fdc4 是新创建容器的虚拟网卡

2、容器的网络配置

linux查看mac地址

ip addr show                       (ip address show 、ip addr ) 查看本机ip和额外的一些信息

ifconfig -a                        其中 HWaddr 就是mac地址

cat /sys/class/net/eth0/address    查看eth0的mac地址

cat /proc/net/arp   

进入容器,查看网络配置

docker  exec  -it  e5139668ecf6   bash

容器有一个网卡 eth0

实际上容器中的 eth0和host中的 vethddb21c8@if6 是一对 veth pair

veth pair 是一种成对出现的特殊网络设备,可比作由一根虚拟网线连接起来的一对网卡,网卡的一头(eth0)在容器中,另一头(vethddb21c8@if6)挂在网桥 docker0 上,其效果就是将 eth0 也挂在了 docker0 上

eth0配置了172.17.0.3的IP地址

3、bridge 网络的配置信息

docker   network   inspect   bridge

bridge 网络配置的 subnet 就是 172.17.0.0/16,并且网关是 172.17.0.1

ifconfig docker0

容器创建时,docker 会自动从 172.17.0.0/16 中分配一个 IP

三、user-defined 网络

Docker 提供三种 user-defined 网络驱动:bridge, overlay 和 macvlan

overlay 和 macvlan 用于创建跨主机的网络

1、创建自定义bridge 网络

brctl  show

A、自定义创建bridge网络

docker  network  create  --driver  bridge  myself-net

brctl  show

网桥br-c34b6df765be为新创建的,c34b6df765be是self-net网络长ID对应的短ID

c34b6df765befbd7609a6bb8007fc8d29afba3de3d4a152b95d4a96172cd8866

查看一下 self-net 的配置信息

docker network inspect  self-net

[root@docker-centos ~]# docker network inspect  self-net

[

    {

        "Name": "self-net",

        "Id": "c34b6df765befbd7609a6bb8007fc8d29afba3de3d4a152b95d4a96172cd8866",

        "Created": "2020-05-22T16:59:22.711670578+08:00",

        "Scope": "local",

        "Driver": "bridge",

        "EnableIPv6": false,

        "IPAM": {

            "Driver": "default",

            "Options": {},

            "Config": [

                {

                    "Subnet": "172.18.0.0/16",

                    "Gateway": "172.18.0.1"

                }

            ]

        },

        "Internal": false,

        "Attachable": false,

        "Ingress": false,

        "ConfigFrom": {

            "Network": ""

        },

        "ConfigOnly": false,

        "Containers": {},

        "Options": {},

        "Labels": {}

    }

]

Docker自动分配的IP网段:172.18.0.0/16

指定网段,创建容器:

docker  run  -it  --network=self-net  busybox

Docker自动分配的IP地址:172.18.0.2

B、自定义创建指定子网网络

创建时需要指定参数:

--subnet

--gateway

创建指定网段的网络:

docker  network  create  --driver  bridge  --subnet  172.16.128.0/24  --gateway  172.16.128.1  self-net-02

brctl show

ifconfig br-1bf920351b57

[root@docker-centos ~]# docker network inspect  self-net-02

[

    {

        "Name": "self-net-02",

        "Id": "1bf920351b57c3d9e002fc5e20367685bc51945c4098ad85aa984afb8577363f",

        "Created": "2020-05-22T17:14:25.536769431+08:00",

        "Scope": "local",

        "Driver": "bridge",

        "EnableIPv6": false,

        "IPAM": {

            "Driver": "default",

            "Options": {},

            "Config": [

                {

                    "Subnet": "172.16.128.0/24",

                    "Gateway": "172.16.128.1"

                }

            ]

        },

        "Internal": false,

        "Attachable": false,

        "Ingress": false,

        "ConfigFrom": {

            "Network": ""

        },

        "ConfigOnly": false,

        "Containers": {},

        "Options": {},

        "Labels": {}

    }

]

2、容器使用指定网络

在容器启动时,指定容器需要使用的特定网络

--network

A、指定容器使用的网络

docker  run  -it  --network=self-net-02  busybox

ip  a

容器自动分配到IP地址:172.16.128.2

B、指定容器使用的IP地址(容器使用静态IP)

--ip

docker  run  -it  --network=self-net-02  --ip 172.16.128.88  busybox

容器的指定IP地址:172.16.128.88

注意:只有使用 --subnet 创建的网络启动容器时才能指定静态 IP

否则,会报错!

self-net在创建时,没有用 --subnet  指定网段,所以在启动容器时,若是指定固定IP会报错:docker: Error response from daemon: user specified IP address is supported only when connecting to networks with user configured subnets.

ERRO[0000] error waiting for container: context canceled

3、自定义网络中容器间通讯

2个 busybox 容器都挂在 self-net-02 上,互通测试

172.16.128.2

172.16.128.88

docker exec -it 3eaf226a84c2  sh

ip  a

ping   172.16.128.88

ping   172.16.128.1

同一网络中的容器、网关之间都是可以通信的

4、自定义网络之间容器间通讯

172.18.0.0/16段,容器IP地址:172.18.0.2,网关:172.18.0.1

172.16.128.0/24段,容器IP地址:172.16.128.2,网关:172.16.128.1

A、默认情况下:属于不通网段容器之间的网络是不通的!

docker  run  -it  --network=self-net  busybox

ping  -c 2 172.16.128.1  (网关通)

ping  -c 2 172.16.128.2  (容器不通)

B、如何打通不通网段之间容器的访问?

前提条件:

host 上对每个网络的都有一条路由

操作系统上打开了 ip forwarding

host 成为一个路由器,挂接在不同网桥上的网络就能够相互通信

(1)  172.16.128.0/24段 和 172.18.0.0/16段 路由定义已经存在

route -F

route -n

ip  r

(2)  路由转发ip forwarding已经开启

sysctl net.ipv4.ip_forward

 

  1.  最后,查看iptables规则

iptables-save | grep DROP

iptables-save | grep DOCKER-ISOLATION-STAGE

isolation隔离

!表示除了的意思

DOCKER-ISOLATION 规则的命名,可知 docker 在设计上就是要隔离不同的 netwrok

如何让 不同网段 busybox 通信?

方法:在容器中加入需要通信的网段的网卡

给容器添加1张指定网段的网卡:

docker   network   connect  指定网络名称   容器ID

基本网络状况:

68694e564dc3容器  属于self-net网段

7b5e8a86db80 和 3eaf226a84c2容器 属于 self-net-02网段

现在给68694e564dc3容器添加一张self-net-02网段的网卡:

docker   network   connect  self-net-02  68694e564dc3

进入添加网卡的容器

docker  exec  -it 68694e564dc3 sh

查看容器的ip地址

ip a

测试网络连通性

ping  -c 2 172.16.128.2

ping  -c 2 172.16.128.88

容器68694e564dc3增加了一张  self-net-02 网络的网卡eth1 ,IP地址为172.16.128.3

测试 self-net-02 网络的7b5e8a86db80 和 3eaf226a84c2容器,网络可以ping通

四、容器间的相互通信---3种

1、IP 通信

容器间通信,必须每一个容器中有属于同一个网络的网卡

方法1:容器创建时通过 --network 指定相应的网络

方法2:docker network connect 容器加入到指定网络

2、Docker DNS Server

IP 访问容器不够灵活,优化方案 docker 的 DNS 服务

从 Docker 1.10 版本开始,docker daemon 实现了一个内嵌的 DNS server,使容器可以直接通过“容器名”通信

方法:启动时用 --name 指定容器命名

使用范围:只能在 user-defined 自定义网络中使用,默认的 bridge 网络是无法使用 DNS 的

  1. 情景1:使用定义网络self-net-02

创建2个容器busybox-1和busybox-2

docker run -it --network=self-net-02 --name=busybox-1 busybox

docker run -it --network=self-net-02 --name=busybox-2 busybox

busybox-1 就可以直接 ping 到 busybox-2

docker  restart $(docker ps -aq -f status=exited)

docker  exec -it busybox-1 sh

ping  busybox-2

B、情景2:使用默认bridge网络

创建2个容器busybox-3和busybox-4

docker run -it  --name=busybox-3  busybox

docker run -it  --name=busybox-4  busybox

busybox-3 不能 ping 通 busybox-4

docker  restart $(docker ps -aq -f status=exited)

docker  exec -it busybox-3 sh

ping  busybox-4

 

容器名 busybox-4 是ping 不通的

3、joined 容器

joined 容器使n个容器共享1个网络栈,共享网卡和配置信息,joined 容器之间可以通过 127.0.0.1 直接通信

第一步:创建名为 web1 的 httpd 容器

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

ip  a

注意:docker的base镜像只包含简单的操作系统,其他命令需要自己安装

apt  update  &&  apt install  -y  iproute2

创建自己的新镜像:

docker  ps

docker  commit  18f212734fa6  httpd_ip

httpd容器的IP地址和Mac地址:

    link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0

    inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0

第二步:创建 busybox 容器并通过 --network=container:web1 指定 jointed 容器为 web1:

docker  run  -it  --network=container:web1 --name=jointed-web1   busybox

wget 127.0.0.1

cat index.html

busybox容器的IP地址和Mac地址:

    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

busybox 和 web1 的网卡 mac 地址与 IP 一样,共享相同的网络栈

busybox 可用 127.0.0.1 访问 web1 的 http 服务

joined 容器适用场景:

不同容器中的程序通过 loopback 高效快速地通信,比如 web server 与 app server

监控其他容器的网络流量,比如运行在独立容器中的网络监控程序

获取所有容器以及IP地址:

docker inspect -f '{{.Name}} - {{.NetworkSettings.IPAddress }}' $(docker ps -aq)

使用docker-compose命令为,

docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)

docker inspect --format='{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)

查看单个容器的IP地址:

docker inspect --format '{{ .NetworkSettings.IPAddress }}' 18f212734fa6

docker inspect 18f212734fa6

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 18f212734fa6

五、容器访问外部

当docker host可以访问Internet时,之上创建的容器默认也是可以上Internet

容器默认就能访问外网----外网指的是容器网络以外的网络

分析原理:

iptables  -t  nat   -S

iptables  -t  nat   -S  | grep docker0

其中有1条规则:

-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

规则解析:

如果网桥 docker0 收到来自 172.17.0.0/16 网段的外出包,把它交给 MASQUERADE 处理

MASQUERADE 的处理方式是将包的源地址替换成 host 的地址发送出去,即做了一次网络地址转换(NAT)

查看地址是如何转换的:

1、docker host 的路由表

ip  r

解析:

默认路由通过 ens33 发出去,所以我们要同时监控 ens33 和 docker0 上的 icmp(ping)数据包

当 httpd容器 18f212734fa6 去 ping baidu.com 时,tcpdump 输出如下:

httpd容器中安装ping命令:

apt-get update && apt-get install iputils-ping

ping  -c 3 baidu.com

host 上安装tcpdump

yum -y install tcpdump

tcpdump   -i  docker0  -n  icmp

解析:

docker0 收到 httpd容器 的 ping 包,源地址为容器 IP 172.17.0.4,交给 MASQUERADE 处理

MASQUERADE 处理--网络地址转换(NAT)之后,观察 ens33 的ping包源地址变化

tcpdump   -i  ens33  -n  icmp

解析:

ens33 收到的 ping 包,源地址为容器 IP 192.168.233.144,即为host本机地址

NAT过程分步骤:

A、 httpd容器 发送 ping 包:172.17.0.4 > www.baidu.com

B、 docker0 收到ping包,发现是发送到外网的,交给 NAT 处理

C、 NAT 将源地址换成 ens33 的 IP:192.168.233.144 > www.baidu.com

D、 ping 包从 ens33 发送出去,到达 www.baidu.com

六、外部访问容器

docker 将容器对外提供服务的端口映射到 host 的某个端口,外网通过该端口访问容器

容器启动时,-p参数映射端口

A、动态映射到host端口

docker  run -d  --name=web02  -p 80  httpd_ip

docker  run -d  --name=web03  -p 80  httpd

查看容器在host上的映射端口:

docker port 95c6bc1f7b8f    web03

80/tcp -> 0.0.0.0:32771

docker port 9a5c3e003dd6    web02

80/tcp -> 0.0.0.0:32770

httpd 容器web03的 80 端口被映射到 host 32771 上,通过 <host ip>:<32771> 访问容器的 web 服务了

httpd 容器web02的 80 端口被映射到 host 32770 上

curl  192.168.233.144:32771

curl  192.168.233.144:32770

 

 

B、映射指定到host端口

httpd容器的 80 端口映射到 host 的 8080 端口

docker  run -d  --name=web04  -p host端口:容器端口  httpd

docker  run -d  --name=web04  -p 8080:80            httpd

docker  port 486e6c224c28

curl 192.168.233.144:8080

 

原理解析:

每一个映射的端口,host 都会启动一个 docker-proxy 进程来处理访问容器的流量

ps  -ef  |  grep  docker-proxy

A、docker-proxy 监听 host 的 8080 端口

B、当 curl 访问 192.168.233.144:8080 时,docker-proxy 转发给容器 172.17.0.8:80

C、httpd 容器响应请求并返回结果

查看httpd容器的应用信息:

docker  logs -f  web04

详情请见,微信公众号

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值