前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >6.docker的网络通讯

6.docker的网络通讯

作者头像
用户7798898
发布2020-09-27 16:54:40
1K0
发布2020-09-27 16:54:40
举报

一. docker网络通讯的模式

docker 网络通讯的几种形式

1. 容器与容器之间

2. 容器访问外部网络

3. 外部网络访问容器

1.1 容器和容器之间如何进行通讯的?

1. 每台机器上都有一个网卡,有的甚至有两个网卡 , ETHD 10.1.1.10/8就表示一个网卡

2. docker启动以后, 会出现一个docker0,我们可以通过ifconfig来查看

我们发现, 有一个docker0, docker0是什么?我们可以将其理解为交换机,术语称之为网桥, 那交换机有什么作用?交换不同容器之间的数据, 让数据间可以交流。

交换机一旦创建以后, 就会创建一个叫namespace的东西,名字叫做network namespace. 全名叫做网络命名空间.也就是上图中蓝色方框VethX,不同的网络命名空间会形成相互隔离,一端固定在容器内容, 成为虚拟网卡, 另一端固定在本机。

进入到容器查看ip a,可以看到eth0的网卡

在本机会生成一个类似vethe1abf09@if26的网卡与容器中的网卡相对应。

只要多一个容器就会多一个veth。也就是说一端在容器里,另一端在本机里,作为连通的作用。 并且, 网络命名空间会将不同的网络隔离开来,各用个的。这样就实现了隔离,以及怎样与本机进行交互。这样,容器和容器之间就可以通讯了。 这解决的是容器和容器间进行通讯。 这是通过docker0网桥解决的

1.2. 容器如何访问外部网络

iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -o docker0 -j MASQUERADE 这是一个典型的SNAT转换, 这种方式是通过TNAT的方式实现的

1.3 外部网络如何访问容器

docker run -d -p 80:80 apache 外部网络访问容器只需加上-p 80:80, 就会实现下面两个操作。 iptables -t nat -A POSTROUTING -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 这种方式是通过DNAT来实现的

二. 网络模式的修改

docker启动以后, 默认的网桥是docker0, 默认的ip地址172.0.0.1, 我们能不能修改默认的网桥和ip地址呢?接下来就看看有哪些值能被我们修改

1. docker进程网络修改参数

docker进程修改, 后面的容器都会跟着被修改. 相当于是主程序修改, 相应的容器都会跟着修改

  • -b, --bridge="" , 指定docker使用的网桥设备, 默认情况下docker启动的时候会自动创建并使用docker0网桥设备, 通过此参数,可以使用自定义的网桥设备

   也就是说, 我们的网桥是docker0, 如果你想要吧网桥改成docker1, 怎么改呢?设置一个参数--bridge="docker1"就可以了

  • --bip 指定docker0的ip和掩码,使用标准的CIDR形式, 如10.10.10.10/24. 其中24表示的就是子网掩码255.255.255.0. 这是一个默认的表达方式
  • --dns 配置容器的dns, 在启动docker进程的时候添加,所有容器都会生效

2. 容器网络的修改

--dns 用于指定启动的容器的DNS. 只在启动的容器生效 --net 用于指定容器的网络通讯方式, 有以下四个值 

  1. bridge: 网桥方式, 也是docker的默认方式. 也就是通过网桥进行数据通讯, 并且是隔离

2. none: 没有任何的ip地址. 如果启动容器的时候, 使用了--net="none", 通过ip a查看容器的网络, 发现没有连接网络的信息. 也就是说不能和外界联通.

比如: 我们启动一个tomcat

代码语言:javascript
复制
docker run -it --name tomcat11 --net=none tomcat9 /bin/bash

我们在执行ip a查看网络情况. 我们发现没有外网连接.

一个容器,都不能上网了, 那还有什么用呢?

有些容器没必要有网络. 比如:有些容器是做计算的, 这种计算完把结果放在本地了,他不需要有网络,有了网络反而不安全了.只能自己跟自己通讯.

3. container: 使用其他容器的网络栈,Docker容器会加入其他容器的network namespace. 如果使用同一个网络栈, 比如:一个容器是nginx,另一个容器是mysql. nginx就可以向在本地一样访问3306端口了. 这样安全性就差了, 但在有些环境, 就是要求要这种

4. host: 表示容器使用host的网络, 没有自己独立的网络, 容器可以完全访问host的网络,   我们启动一个tomcat:

代码语言:javascript
复制
 docker run --name tomcat11 --net=host -d tomcat:v1.0

  运行这个容器之前, 要确保本机的8080端口没有被使用

  然后在容器里运行curl http://locahost:8080

  再在虚拟机中运行curl http://localhost:8080

我们发现,他们访问的内容是一样, 容器启动的时候没有使用-p 进行端口映射,为什么能访问呢?

  因为容器使用的host主机的网络, 相当于容器启动了8080端口, 默认主机也有这个端口, 所以可以直接访问.

3. 暴露端口

-p/-P 选项的使用

  • -p :<ContainerPort> 将制定的容器端口映射到主机所有地址的一个动态端口.
  • 意思是: 容器端口有了, 你要访问那个主机端口, 不确定, 这个是随机的
  • -p <HostPort>:<ContainerPort> 容器的指定端口映射到主机的指定端口 (最常用)
  • -p <IP>::<ContainerPort> 映射到指定的主机的IP的动态端口
  • -p <IP>:<HostPort>:<ContainerPort> 映射到指定主机ip的主机端口 (最常用)
  • -P , 暴露需要的所有端口

docker port 容器ID, 可以查看容器当前的端口映射关系

4. 自定义docker0网桥的网络地址

/etc/docker/daemon.json文件 { 'bip':"192.168.1.5/24" "final-cidr":"10.20.0.0/36" "default-gateway":"10.20.1.1" "dns":["10.20.1.1", "10.20.1.3"]

}

三. 常见的隔离方式

我们先来看一种情况.

我在192.168.198.142虚拟机上启动两个docker容器

代码语言:javascript
复制
docker run -it --name tomcat1 tomcat9 /bin/bash

docker run -it --name tomcat2 tomcat9 /bin/bash

查看两个容器的ip

tomcat1的ip是172.17.0.2, tomcat2的ip是172.17.0.3.

那么我们在tomcat1中pingtomcat2的ip能不能ping通呢?

代码语言:javascript
复制
ping 172.17.0.3

没问题, 我们看到, 确实是成功了. 这说明什么?

这说明, 如果容器1和容器2相互之间可以通过ip进行访问.

那么,如果我不想让他们之间相互访问, 怎么办呢? 这就是容器和容器之间网络隔离

3.1 容器间网络隔离

所谓容器间网络隔离, 指的是容器和容器之间网络不通, 也就是ping不通.既然ping不通,那么相互之间就不能访问了. 但是依然是可以和主机相互访问的.

下面看几个命令:

代码语言:javascript
复制
docker network ls 

我们看到, 有一个网络是默认的bridge网络. 之所以上面两个tomcat容器之间可以相互访问, 原因是: 他们使用的是同一个网段. 如果我们想实现隔离, 让他们处于不同的网段就可以了.

我们可以通过下面的命令创建新的网段

代码语言:javascript
复制
docker network create -d 网络类型  网络名词
网络类型有两种
    overlay network---主要用在不同的主机中的容器可以互相通信,但是需要借助其他一些软件去实现
    bridge  network---网桥.
代码语言:javascript
复制
下面我们就使用这种网桥来创建两个新的网络
代码语言:javascript
复制
docker network create -d bridge lamp

docker network create -d bridge lnmp

查看当前已有的网络

通过查看本机的ip,我们看到多了两个网络

原来只有172.17.0.1网络, 现在增加了172.18.0.1/16 和 172.19.0.1/16

接下来,我们使用新的网络新建两个容器

新建一个容器tomcat1, 设置他的网络使用lamp, 他的网段是172.18.0.1

代码语言:javascript
复制
docker run -it --name tomcat1 --network=lamp tomcat9 /bin/bash

进入到容器以后, 输入ip a查看容器的ip地址

我们看到容器的ip地址是172.18.0.2

在新建一个容器2, 设置他的网络使用lnmp, 他的网段是172.19.0.1

代码语言:javascript
复制
 docker run -it --name tomcat2 --network=lnmp tomcat9 /bin/bash

进入到容器, 查看容器的ip

我们看到容器2的ip地址是172.19.0.2

现在这两个容器处在不同的网段, 处于不同的两个网段, 他们之间肯定是ping不通的.

在容器1中ping 172.19.0.2, ping不通

反之, 在容器2ping容器1的ip也ping不通. 这样就实现了容器将网络的隔离

我们之前, 搭建的harbor仓库, 我们可以看一下这台服务的已经启动的docker网络

代码语言:javascript
复制
虚拟机:
192.168.198.143

查询docker网络命令
docker network ls

我们看到有一个名字叫做harbor_harbor的网络. 采用的network方式是bridge

3.2 如何让两台主机的两个容器之间可以通讯?

比如: 让ip是192.168.198.142虚拟机上的docker容器能够和192.168.198.143虚拟机上的docker容器进行通讯?

这里需要我们自己去指定网桥.

下面我们要搭建一个网桥, 这个网桥和外界具有真正的通讯能力. 什么叫真正的通讯能力呢?

相对而言, 指的是docker0这个网桥, docker0实际上是一个假的网桥. 他只能让本机的容器间具有通讯的能力. 却不能让不同主机之间的容器进行通讯.

我们现在要配置一个, 使用真正的物理网卡实现的网桥. 这个网桥能够跟外面的主机进行通讯.

创建网桥有多种方法. 可以通过工具创建, 这里我们使用修改配置文件的方式创建网桥. 具体操作如下:

代码语言:javascript
复制
第一步: 进入到/etc/sysconfig/network-scripts/
代码语言:javascript
复制
第二步: 拷贝ifcfg-ens33
       cp -a ifcfg-ens33 ifcfg-br0
代码语言:javascript
复制
第三步: 修改ifcfg-ens33
       删除ip的相关配置, 增加网桥配置BRIDGE=br0
代码语言:javascript
复制
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
#BOOTPROTO="dhcp"
BOOTPROTO="static"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_FAILURE_FATAL="no"
IPV6_ADDR_GEN_MODE="stable-privacy"
NAME="ens33"
UUID="1c73d826-0a58-4e97-8fd2-63ad33c4a5ad"
DEVICE="ens33"
ONBOOT="yes"
BRIDGE="br0"    // 增加BRIDGE

删除下面几项
IPADDR=192.168.198.142
NETMASK=255.255.255.0
GATEWAY=192.168.198.2
BROADCAST=192.168.198.255
DNS1=192.168.198.2
代码语言:javascript
复制
第四步: 修改ifcfg-br0
    删除全部配置, 重新添加以下内容. 注意重新设置ip
代码语言:javascript
复制
DEVICE=br0
TYPE=Bridge
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.198.142
NETMASK=255.255.255.0
GATEWAY=192.168.198.2
BROADCAST=192.168.198.255
DNS1=192.168.198.2
代码语言:javascript
复制
第五步: 重启网络
    systemctl network restart
代码语言:javascript
复制
第六步: 此时查看ip a
我们发现ens3的ip地址没有了, 多了一个br0的网桥

默认情况下,docker并不能介入到br0去通讯 我们可以使用pipework来打通docker容器和br0网络

下面, 设置pipework网络

代码语言:javascript
复制
1. 下载git  
   yum install -y git
代码语言:javascript
复制
2. git clone https://github.com/jpetazzo/pipework
3. cp pipework/pipework /usr/local/bin/
    chmod a+x /usr/local/bin/pipework
代码语言:javascript
复制
4. 启动容器, 设置--net为none
    docker run  --net=none --name tomcat -d tomcat9
    这里--net必须设置成none, 这样后面我们才能通过pipework给他设置一个独立的ip地址
代码语言:javascript
复制
5. 通过pipework赋予容器一个独立的ip地址 
  pipework 网桥类型  容器名称 ip地址
  pipework br0 tomcat 192.168.198.145/24
代码语言:javascript
复制
6. 验证网络

首先, 进入到容器, 查看容器的网络

我们看到容器的网络确实设置为192.168.198.145

接下来, 接下来, 我在本机mac上ping刚刚设置的192.168.198.145.是可以ping通的

然后在容器里, 虚拟机里, 本机macos上ping 192.168.198.145:8080都可以看到tomcat的启动页. 说明容器配置成功了

这时容器也有自己独立的ip了. 我们在另一台虚拟机上192.168.198.143上ping 192.168.198.145, 我们发现也是可以ping通的了.

而且也可以访问http://192.168.198.145:8080 并且能够看到tomcat的启动页

现在容器有了自己独立的ip, 可以和各种主机/容器进行通讯了.

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-06-11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一. docker网络通讯的模式
    • 1.1 容器和容器之间如何进行通讯的?
      • 1.2. 容器如何访问外部网络
        • 1.3 外部网络如何访问容器
        • 二. 网络模式的修改
          • 1. docker进程网络修改参数
            • 2. 容器网络的修改
              • --dns 用于指定启动的容器的DNS. 只在启动的容器生效 --net 用于指定容器的网络通讯方式, 有以下四个值 
            • 3. 暴露端口
              • -p/-P 选项的使用
                • docker port 容器ID, 可以查看容器当前的端口映射关系
              • 4. 自定义docker0网桥的网络地址
              • 三. 常见的隔离方式
                • 3.1 容器间网络隔离
                  • 新建一个容器tomcat1, 设置他的网络使用lamp, 他的网段是172.18.0.1
                  • 在新建一个容器2, 设置他的网络使用lnmp, 他的网段是172.19.0.1
                • 3.2 如何让两台主机的两个容器之间可以通讯?
                  • 默认情况下,docker并不能介入到br0去通讯 我们可以使用pipework来打通docker容器和br0网络
              相关产品与服务
              容器服务
              腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档