docker的网络通讯

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: docker的网络通讯

目录:

1. docker网络通讯的模式

2. docker网络模式的修改

3. 常见隔离方式


 

一. docker网络通讯的模式


docker 网络通讯的几种形式

1. 容器与容器之间

2. 容器访问外部网络

3. 外部网络访问容器

 

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

1187916-20200610205438667-1678161991.png

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

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


1187916-20200610210012741-332541221.png

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

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

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


1187916-20200610210301553-964784281.png


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


1187916-20200610210554269-458378370.png


只要多一个容器就会多一个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

docker run -it --name tomcat11 --net=none tomcat9 /bin/bash

1187916-20200611194600265-1150913878.png


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


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


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


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


  4. host: 表示容器使用host的网络, 没有自己独立的网络, 容器可以完全访问host的网络,

  我们启动一个tomcat:

docker run --name tomcat11 --net=host -d tomcat:v1.0

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

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


1187916-20200611194905048-1112592374.jpg

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


1187916-20200611194915723-23096761.jpg


  我们发现,他们访问的内容是一样, 容器启动的时候没有使用-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容器


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

查看两个容器的ip

1187916-20200612071024127-162166229.png

1187916-20200612071045240-845889907.png

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

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


ping 172.17.0.3

1187916-20200612071220866-626125625.png


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

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

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


3.1 容器间网络隔离


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

下面看几个命令:


docker network ls 

1187916-20200612072311214-1442921699.png

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


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

docker network create -d 网络类型  网络名词
网络类型有两种
    overlay network---主要用在不同的主机中的容器可以互相通信,但是需要借助其他一些软件去实现
    bridge  network---网桥.

下面我们就使用这种网桥来创建两个新的网络


docker network create -d bridge lamp
docker network create -d bridge lnmp

1187916-20200612073058083-377500276.png

查看当前已有的网络

1187916-20200612073129264-1765138991.png

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

1187916-20200612073248777-980616991.png

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

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


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

docker run -it --name tomcat1 --network=lamp tomcat9 /bin/bash

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

1187916-20200612101013162-1556231692.png

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

 

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

 docker run -it --name tomcat2 --network=lnmp tomcat9 /bin/bash

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

1187916-20200612101112028-2134149043.png

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

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

在容器1中ping 172.19.0.2, ping不通


1187916-20200612101302598-9962863.png


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

 

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

虚拟机:
192.168.198.143
查询docker网络命令
docker network ls

1187916-20200612101841152-1003316960.png

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

 

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


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


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


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

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

 

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

 

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

第一步: 进入到/etc/sysconfig/network-scripts/
第二步: 拷贝ifcfg-ens33
       cp -a ifcfg-ens33 ifcfg-br0
第三步: 修改ifcfg-ens33
       删除ip的相关配置, 增加网桥配置BRIDGE=br0
复制代码
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
复制代码
第四步: 修改ifcfg-br0
    删除全部配置, 重新添加以下内容. 注意重新设置ip
复制代码
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
复制代码
第五步: 重启网络
    systemctl network restart
第六步: 此时查看ip a
我们发现ens3的ip地址没有了, 多了一个br0的网桥

1187916-20200612145457901-1182659875.png


默认情况下,docker并不能介入到br0去通讯

我们可以使用pipework来打通docker容器和br0网络


下面, 设置pipework网络

1. 下载git  
   yum install -y git
2. git clone https://github.com/jpetazzo/pipework
3. cp pipework/pipework /usr/local/bin/
    chmod a+x /usr/local/bin/pipework
4. 启动容器, 设置--net为none
    docker run  --net=none --name tomcat -d tomcat9
    这里--net必须设置成none, 这样后面我们才能通过pipework给他设置一个独立的ip地址

1187916-20200612150217333-624032182.png

5. 通过pipework赋予容器一个独立的ip地址 
  pipework 网桥类型  容器名称 ip地址
  pipework br0 tomcat 192.168.198.145/24

1187916-20200612150240193-21769427.png

6. 验证网络

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

1187916-20200612150337957-1295907323.png

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


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


1187916-20200612150514164-53068260.png


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

1187916-20200612150626610-961824233.png


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


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

1187916-20200612150810625-1324051002.png


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

相关文章
|
4月前
|
存储 安全 数据安全/隐私保护
Docker进阶:网络配置与服务编排
【10月更文挑战第17天】随着微服务架构的流行,Docker作为容器化技术的领导者,在企业级应用部署中扮演着重要角色。掌握Docker的高级特性,特别是网络配置和服务编排,对于构建高效、可维护的分布式系统至关重要。本文将深入探讨Docker的网络配置选项、容器间通信机制、端口映射技术以及使用Docker Compose进行多容器应用部署的最佳实践。
95 8
|
2月前
|
NoSQL 关系型数据库 MySQL
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
201 56
《docker高级篇(大厂进阶):4.Docker网络》包括:是什么、常用基本命令、能干嘛、网络模式、docker平台架构图解
|
4月前
|
Docker 容器
docker中默认桥接网络
【10月更文挑战第7天】
199 62
|
2月前
|
安全 Docker 容器
docker的默认网络模式有哪些
Docker 默认网络模式包括:1) bridge:默认模式,各容器分配独立IP,可通过名称或IP通信;2) host:容器与宿主机共享网络命名空间,性能最优但有安全风险;3) none:容器隔离无网络配置,适用于仅需本地通信的场景。
74 6
|
2月前
|
存储 缓存 监控
Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
本文介绍了Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
232 7
|
3月前
|
安全 网络安全 数据安全/隐私保护
利用Docker的网络安全功能来保护容器化应用
通过综合运用这些 Docker 网络安全功能和策略,可以有效地保护容器化应用,降低安全风险,确保应用在安全的环境中运行。同时,随着安全威胁的不断变化,还需要持续关注和研究新的网络安全技术和方法,不断完善和强化网络安全保护措施,以适应日益复杂的安全挑战。
65 5
|
4月前
|
Docker 容器
docker swarm启动服务并连接到网络
【10月更文挑战第16天】
79 5
|
4月前
|
调度 Docker 容器
docker swarm创建覆盖网络
【10月更文挑战第16天】
68 5
|
4月前
|
负载均衡 应用服务中间件 数据安全/隐私保护
docker swarm 创建 Swarm 模式下的网络
【10月更文挑战第14天】
117 6
|
4月前
|
负载均衡 网络协议 关系型数据库
docker swarm 使用网络启动服务
【10月更文挑战第15天】
62 4