一、docker网络概述

1、docker网络实现的原理

Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,成为Container-IP,同时Docker’网桥是 每个容器的默认网关。
因为同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。
Docker网桥是宿主机虚拟出来的,并不是真实存在网络设备,外部网络是无法寻址到的,这也意味着外部网络无法直接通过Container-IP访问到容器。
如果容器希望外部访问能访问到,可以通过映射容器端口到宿主主机(端口映射),即 docker run创建容器时通过-p或-P参数来启用,访问容器的时候就通过[宿主机IP]:[容器端口]访问容器 。

2、容器的端口映射

1).端口映射

  • 把容器的端口映射为宿主机的一个随机或者特定端口,使用外部用户可以访问容器服务
  • 端口映射本是在容器底层做了 iptables 地址转发,出去的流量做 SNAT 源地址转发,进来的流量做 DNAT 目标地址转发。

2).四种端口映射

  • 随机端口映射:就是把容器的端口随机映射为宿主机的一个端口。
  • 指定端口映射:就是把容器的端口映射为宿主机的指定端口。
  • 指定网卡随机端口映射:就是把容器的端口映射为宿主机的指定网卡的随机端口。
  • 指定网卡端口映射:就是把容器的端口映射为宿主机的指定网卡的指定端口。

3).端口映射演示

(1).随机端口映射(-P)

把 容器 8080 的端口映射到宿主机的随机端口

docker run -itd -P centos:latest

image-20230912145937147

(2).指定端口映射(-p 宿主机端口:容器端口)

将 web 容器的 8080 端口指定映射到宿主机的 8000 端口

docker run -itd -p 8000:8080  --name web centos 

image-20230912150024699(3).指定网卡随机端口映射(-p ::)

将 tomcat 容器的 8080 端口映射到宿主机 ens33 网卡的随机端口

docker run -itd -p 192.168.153.130::8080   --name tomcat  centos 
其中:192.168.153.130宿主机ip

image-20230912150141319

查看映射结果,容器 8080 端口映射到了宿主机的192.168.153.130:49153 端口

(4).指定网卡指定端口映射(-p 宿主机IP:宿主机端口:容器端口)

将 mysql 容器的 3306 端口映射到宿主机 ens33 网卡的 13306 端口

docker run -itd -p 192.168.153.130:13306:3306  --name mysql   centos 

image-20230912150332366

二、docker的网络模式

1.前言

四类网络模式:

选项 描述
HOSt 基础镜像(容器不会虚拟出自己的网卡,配置主机的IP等,而是使用宿主机的IP和端口;
Container 创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP,端口范围;
None 该模式关闭了网络功能
Bridge 默认为该模式,此模式会为每一个容器分配,设置IP等,并将容器连接到一个docker0的虚拟网桥,通过docker0网桥以及iptables nat表配置与宿主机通信。

2.默认网络

当你安装Docker时,它会自动创建三个网络Bridge(创建容器,默认连接到此网络)、none、host。你可以使用一下docker network ls 或者docker network list命令列出这些网络:

docker network ls
docker network llist

image-20230912150757039

3.使用docker run 创建Docker容器,可以用–net或–network选项指定的网络模式

选项 描述
host模式 使用--net=host指定;
none模式 使用--net=hnone指定;
container模式 使用--net=container:NAME_ _or_ID指定;
bridge模式 使用--net=bridge指定;

三、docker网络模式详解

1.host模式

host 模式: 使用–net=host模式指定
相当于VMware中的桥接模式,与宿主机在同一个网络中,但没有独立的IP地址。

Docker 使用了Linux的Namespace技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。一个Network Namespace提供了一份独立的网络环境,包括网卡,路由,iptables 规则等都与其他Network Namespace隔离。一个Docker容器一般会分配一个独立的Network Namespace。

Namespace的简要说明:
Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。
一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其他的NetworkNamespace隔离。一个Docker容器一般会分配一个独立的Network Namespace。

但是如果启动容器的时候使用host模式,name这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口范围。此时容器不再拥有隔离的、独立的网格栈,不拥有所有的端口资源。
image-20230912151257264

docker run -itd  --name   net-test -p 80  mycentos:1.0  /bin/bash
docker run -itd  --name   net-test1 -p 80  mycentos:1.0  /bin/bash
docker ps
docker attach net-test
ifconfig

image-20230912151358970

2.container模式(K8S使用的模式)

这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信
image-20230912151552480

docker ps
#查看容器进程PID
docker inspect -f '{{.State.Pid}}' net-test
#查看容器进程、网络、文件系统等命名空间编号
ls -l /proc/容器进程PID/ns

image-20230912151652727

3.none模式

使用none 模式,docker 容器有自己的network Namespace ,但是并不为Docker 容器进行任何网络配置。也就是说,这个Docker 容器没有网卡,ip, 路由等信息。
这种网络模式下,容器只有lo 回环网络,没有其他网卡。
这种类型没有办法联网,但是封闭的网络能很好的保证容器的安全性,该容器将完全独立于网络,用户可以根据需要为容器添加网卡。此模式拥有所有端口。特殊情况下才会用到,一般不用。

image-20230912152424414

4.bridge模式

当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。

从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。

bridge模式是docker的默认网络模式,相当于Vmware中的 nat 模式,不写–net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看

bridge模式如下图所示:

image-20230912151939696

四、docker network命令详解

1.network所有的子命令

命令名称 说明
docker network connect 将容器连接到网络
docker network create 创建一个网络
docker network disconnect 断开容器的网络
docker network inspect 显示一个或多个网络的详细信息
docker network ls 列出所有网络
docker network prune 删除所有未使用的网络
docker network rm 删除一个或多个网络

1).语法 docker network connect命令用于将容器连接到网络。可以按名称或ID连接容器。 一旦连接,容器可以与同一网络中的其他容器通信。 用法:

docker network connect [OPTIONS] NETWORK CONTAINER

选项

名称,简写 默认 说明
--alias 为容器添加网络范围的别名
--ip 指定IP地址
--ip6 指定IPv6地址
--link 添加链接到另一个容器
--link-local-ip 添加容器的链接本地地址

2).将正在运行的容器连接到网络

将正在运行的容器(my_container1)连接到网络(multi-host-network)

docker network connect multi-host-network my_container1

启动容器时将其连接到网络(multi-host-network)
还可以使用docker run --network=选项启动容器并立即将其连接到网络

docker run -itd --network=multi-host-network busybox-container

3).指定容器的IP地址

可以指定要分配给容器网络接口的IP地址。

docker network connect --ip 10.10.36.122 multi-host-network container2

4).使用legacy —link选项

可以使用–link选项将另一个容器与首选别名相链接

docker network connect --link container1:c1 multi-host-network container2

为容器创建一个网络别名
–alias选项可用于通过连接到的网络中的另一个名称来解析容器。

docker network connect --alias db --alias mysql multi-host-network container2

5).停止,暂停或重新启动容器的网络影响

可以暂停,重新启动并停止连接到网络的容器。容器在运行时连接到其配置的网络

docker network create --subnet 172.20.0.0/16 --ip-range 172.20.240.0/20 multi-host-network
docker network connect --ip 172.20.128.2 multi-host-network container2

2.docker network create

1).语法

docker network create命令用于创建一个新的网络连接。 DRIVER接受内置网络驱动程序的桥接或覆盖。如果安装了第三方或自己的自定义网络驱动程序,则可以在此处指定DRIVER。 如果不指定–driver选项,该命令将为您自动创建一个桥接网络。 当安装Docker Engine时,会自动创建桥接网络。 该网络对应于Engine传统依赖的docker0网桥。 当启动使用docker run运行新容器时,它将自动连接到此桥接网络。不能删除此默认网桥,但可以使用network create命令创建新的网络。

docker network create [OPTIONS] NETWORK
名称,简写 默认 说明
--attachable false 启用手动容器安装
--aux-address map[] 网络驱动程序使用的辅助IPv4或IPv6地址
--driver, -d bridge 驱动程序管理网络
--gateway 用于主子网的IPv4或IPv6网关
--internal false 限制对网络的外部访问
--ip-range 从子范围分配容器ip
--ipam-driver default IP地址管理驱动程序
--ipam-opt map[] 设置IPAM驱动程序的具体选项
--ipv6 false 启用IPv6网络
--label 在网络上设置元数据
--opt, -o map[] 设置驱动程序特定选项
--subnet 表示网段的CIDR格式的子网

2).连接容器网络

启动容器时,使用–network标志将其连接到网络。 此示例将busybox容器添加到mynet网络:

docker run -itd --network=mynet busybox

如果要在容器运行后将容器添加到网络,请使用docker network connect子命令

3).指定高级选项

创建网络时,引擎默认为网络创建一个不重叠的子网。 该子网不是现有网络的细分。 它纯粹用于IP寻址目的。可以覆盖此默认值,并使用–subnet选项直接指定子网络值。 在桥接网络上,只能创建单个子网:

docker network create --driver=bridge --subnet=192.168.0.0/16 br0

另外,还可以指定–gateway --ip-range和–aux-address选项。

docker network create \
  --driver=bridge \
  --subnet=172.28.0.0/16 \
  --ip-range=172.28.5.0/24 \
  --gateway=172.28.5.254 \
  br0

如果省略–gateway标志,引擎将从首选池中选择一个。对于覆盖网络和支持它的网络驱动程序插件,可以创建多个子网络。

docker network create -d overlay \
  --subnet=192.168.10.0/25 \
  --subnet=192.168.20.0/25 \
  --gateway=192.168.10.100 \
  --gateway=192.168.20.100 \
  --aux-address="my-router=192.168.10.5" --aux-address="my-switch=192.168.10.6" \
  --aux-address="my-printer=192.168.20.5" --aux-address="my-nas=192.168.20.6" \
  my-multihost-network

确保子网不重叠。如果重叠的话网络创建失败,并且引擎会返回错误。

4.)桥接驱动程序选项

创建自定义网络时,默认的网络驱动程序(即bridge)具有可以传递的其他选项。
例如,使用-o或–opt选项在发布端口时指定IP地址绑定

docker network create \
    -o "com.docker.network.bridge.host_binding_ipv4"="172.19.0.1" \
    simple-network

3、docker network disconnect

1.语法

docker network disconnect命令用于断开容器的网络。容器必须运行才能将其与网络断开连接。

用法:

docker network disconnect [OPTIONS] NETWORK CONTAINER

选项:

名称,简写 默认 说明
--force, -f false 强制容器断开网络的连接

2.示例

docker network disconnect multi-host-network container1

4、显示一个或多个网络的详细信息(docker network inspect)

1).语法

docker network inspect命令用于显示一个或多个网络的详细信息。它返回有关一个或多个网络的信息。 默认情况下,此命令将所有结果呈现在JSON对象中。
用法

docker network inspect [OPTIONS] NETWORK [NETWORK...]

2).示例

docker network disconnect multi-host-network container1

5、列出网络(docker network ls)

1).语法

docker network ls命令用于列出网络。列出引擎守护进程知道的所有网络。 这包括跨群集中多个主机的网络。

过滤
当前支持的过滤器有:

  • 1、驱动器
  • 2、id(网络ID)
  • 3、label(label = 或label = = )
  • 4、名称(网络名称)
  • 5、类型(custom | builtin)
docker network ls [OPTIONS]

选项

名称,简写 默认 说明
--filter, -f 提供过滤器值(例如’driver = bridge‘)
--format 使用Go模板的美化网络
--no-trunc false 不要截断输出
-quiet, -q false 只显示网络ID

2)、示例

(1).列出所有网络
docker network ls

image-20230912154318611

(2).使用–no-trunc选项显示完整的网络ID
docker network ls --no-trunc

image-20230912154405004

(3).过滤–DRIVER

驱动程序过滤器根据驱动程序匹配网络。以下示例将网络与桥驱动程序相匹配:

docker network ls --filter driver=bridge

image-20230912154435465

(4).过滤–ID

id过滤器匹配网络ID的全部或部分。以下过滤器匹配所有具有包含804f74e6eb17bcadac76f0f3…字符串的ID的网络。

docker network ls --filter id=804f74e6eb17bcadac76f0fd2fbd01ed76aa31e2e854799fb6cef2d0beb6ba33

image-20230912154504765

还可以过滤ID中的子字符串,如下所示:

docker network ls --filter id=804f74e6eb17
docker network ls --filter id=80

image-20230912154528328

(5).过滤–标签

标签过滤器基于单独存在标签或标签和值来匹配网络。以下过滤器将网络与使用标签进行匹配,而不管其值。
以下过滤器将网络与使用标签与prod值进行匹配。

docker network ls -f "label=usage=prod"
(6).过滤–名称

名称过滤器匹配网络名称的全部或部分。以下过滤器与包含net-test字符串的名称匹配所有网络。
也可以筛选名称中的子字符串,如下所示:

docker network ls --filter name=net-test

image-20230912154618253

(7).过滤–类型

类型过滤器支持两个值; 内置显示预定义网络(桥,无,主机),而自定义显示用户定义的网络。以下过滤器与所有用户定义的网络相匹配

docker network ls --filter type=custom

image-20230912154707454

有了这个标志,它允许批量清理。 例如,使用此过滤器删除所有用户定义的网络:

docker network rm 'docker network ls --filter type=custom -q'
(8).格式化

格式化选项(–format)使用Go模板打印网络输出。
以下示例使用不带标题的模板,并输出用冒号分隔所有网络的ID和驱动程序条目:

docker network ls --format "{{.ID}}: {{.Driver}}"

image-20230912154806634

6.删除所有未使用的网络

1).前言

docker network prune命令用于删除所有未使用的网络。未使用的网络是不被任何容器引用的网络。
用法

docker network prune [OPTIONS]
名称,简写 默认 说明
--force, -f false 不要提示确认

2).删除所有未连接的网络

docker network prune

image-20230912155003325

7.删除一个或多个网络

1).前言

docker network rm命令用于删除一个或多个网络。按名称或标识符删除一个或多个网络。 要删除网络,必须要先断开连接到它的任何容器的网络。

docker network rm NETWORK [NETWORK...]
名称,简写 默认 说明
--force, -f false 不要提示确认

2).要删除名为“net-test”的网络

docker network rm net-test

3).删除多个网络

要在单个docker network rm命令中删除多个网络,请提供多个网络名称或ID列表。 以下示例删除标识为3695c422697f的网络和名为my-network的网络:

docker network rm 3695c422697f my-network

指定多个网络时,该命令会依次删除每个网络。 如果删除一个网络失败,则该命令继续到列表中的下一个,并尝试删除。 该命令报告每个删除的成功或失败。

五、网桥创建示例(自定义网络)

前面的四种模式是Docker自带的网络模式,其实Docker还有一种叫自定义网络模式

image-20230912155935974

语法:docker network create -d --subnet --gateway <网关> <自定义网路名称>

#创建网络
[root@docker02 ~]# docker network create -d bridge --subnet 192.168.10.0/24 --gateway 192.168.10.1 net-test
ffc46a67356a9143a310eb438bd38da02f2d8569d1f41de2aaec7faa73aaed6e
#查看网络
[root@docker02 ~]# docker network ls
NETWORK ID     NAME       DRIVER    SCOPE
ac1271481467   bridge     bridge    local
7452d6b9af7e   host       host      local
ffc46a67356a   net-test   bridge    local
af803a4e6c40   none       null      local
# 启动容器,并指定自定义的网络
[root@docker02 ~]# docker run  --network net-test  -it -d busybox  /bin/sh
492c49deb76986624df9aa9f0fff4d02fb6aa62c38614e931813f99f7bea0a5d
[root@docker02 ~]# docker ps
CONTAINER ID   IMAGE     COMMAND     CREATED         STATUS         PORTS     NAMES
492c49deb769   busybox   "/bin/sh"   4 seconds ago   Up 3 seconds             wonderful_chatelet