# Docker 网络

# 一、Docker 网络

Docker 网络主要是解决容器联网问题,也是我们使用容器中最重要的一个环节,如果容器没有网络则无法向网络中提供服务。

网络管理命令:docker network

[root@VM-12-10-centos ~]# docker network --helpUsage:	docker network COMMANDManage networksOptions:      --help   Print usageCommands:  connect     Connect a container to a network  create      Create a network  disconnect  Disconnect a container from a network  inspect     Display detailed information on one or more networks  ls          List networks  prune       Remove all unused networks  rm          Remove one or more networksRun 'docker network COMMAND --help' for more information on a command.

# 二、Docker 网络类型

  • bridge
  • host
  • none
  • 容器网络或联盟网络

PS:以下示例均在 Linux 环境下。

# 1. bridge

桥接网络是指容器通过桥接的方式将容器网卡桥接到宿主机的 docker0 网桥,然后再通过宿主机防火墙的 NAT 表实现与外网的联系。

查看宿主机网卡

我们可以使用 ifconfig 来查看宿主机的 docker0 网桥:

[root@zutuanxue ~]# ifconfig 
# docker0 网桥
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:c7ff:fe37:8e8  prefixlen 64  scopeid 0x20<link>
        ether 02:42:c7:37:08:e8  txqueuelen 0  (Ethernet)
        RX packets 6618  bytes 277975 (271.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8152  bytes 24675021 (23.5 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

.....省略了本机的网卡信息

# 容器网卡,每创建一个桥接网络的容器就会生成一个对应的网卡
vethf75a942: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet6 fe80::9085:f5ff:fe34:77b5  prefixlen 64  scopeid 0x20<link>
        ether 92:85:f5:34:77:b5  txqueuelen 0  (Ethernet)
        RX packets 2850  bytes 158484 (154.7 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3397  bytes 11613136 (11.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

如果想看更详细的信息,可以使用 ip add show 命令:

4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:c7:37:08:e8 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:c7ff:fe37:8e8/64 scope link 
       valid_lft forever preferred_lft forever

这里的 vethf75a942@if13 指的就是容器网卡,V 代表虚拟网卡的意思,eth 以太网卡,f75a942 网卡编号,if13 指的是宿主机网桥(docekr0)的一个端口,对应容器的网卡编号加 1。所以容器内的网卡编号应该是 eth0@if14

在容器中执行命令 ip add show 也可以看到:

[root@zutuanxue ~]# docker exec centos1 ip add show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
13: eth0@if14: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

查看宿主机防火墙的 NAT 表内容

使用 iptables -t nat -L 命令可以查看宿主机防火墙的 NAT 表内容:

[root@zutuanxue ~]# iptables -t nat -LChain PREROUTING (policy ACCEPT)target     prot opt source               destination         DOCKER     all  --  anywhere             anywhere             ADDRTYPE match dst-type LOCALChain INPUT (policy ACCEPT)target     prot opt source               destination         Chain OUTPUT (policy ACCEPT)target     prot opt source               destination         DOCKER     all  --  anywhere            !loopback/8           ADDRTYPE match dst-type LOCALChain POSTROUTING (policy ACCEPT)target     prot opt source               destination         MASQUERADE  all  --  172.17.0.0/16        anywhere            Chain DOCKER (2 references)target     prot opt source               destination         RETURN     all  --  anywhere             anywhere   

查看容器网卡和 docker0 网卡的桥接信息

使用 brctl show 可以查看容器网卡和 docker0 网卡的桥接信息:

[root@zutuanxue ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.0242c73708e8	no		vethf75a942

如果 brctl command not found,则需要先安装以太网管理工具:

yum install bridge-utils

# 2. host

容器和真机共用网卡及对应的端口,缺点就是同一个端口只能宿主机或者某个容器使用,其他容器不能用。

# 3. none

容器仅有 lo 网卡,是一个不能联网的本地容器。

# 三、Docker 网桥网络

不同的服务容器组应用不同的网桥,避免同一网络内容器太多,保持容器网络独立性。

关于新网桥联网问题:创建网桥后,宿主机会自动帮你做 NAT,所以不用担心联网问题。

# 1. 查看网络

docker network ls

示例:

[root@VM-12-10-centos ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
4bcb191d2317        bridge              bridge              local
1ba893b67e39        host                host                local
2cfd6854663b        none                null                local

# 2. 创建网桥

docker network create -d bridge --subnet .... --gateway ...  网桥名

示例:

[root@VM-12-10-centos ~]# docker network create -d bridge --subnet 192.168.1.0/24 --gateway 192.168.1.1 mydocker0
966b7623db05c978c01d448ddf81088333ea065cf71863f716f19677108cf9e9
[root@VM-12-10-centos ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
4bcb191d2317        bridge              bridge              local
1ba893b67e39        host                host                local
966b7623db05        mydocker0           bridge              local
2cfd6854663b        none                null                local

# 3. 修改网桥名字

1、关闭新建网桥[root@zutuanxue ~]# ip link set dev br-6a410e27b66e down2、修改名字[root@zutuanxue ~]# ip link set dev br-6a410e27b66e name  mydocker03、启动网桥[root@zutuanxue ~]# ip link set dev mydocker0 up4、重启docker服务[root@zutuanxue ~]# systemctl restart docker

# 4. 删除未使用的网桥

docker network prune

示例:

[root@VM-12-10-centos ~]# docker network prune
WARNING! This will remove all networks not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Networks:
mydocker0

# 5. 删除某个网桥

注意:不能被活动容器占用。

docker network rm 网桥名

示例:

[root@zutuanxue ~]# docker network rm docker100docker100

# 6. 容器连接到网桥

docker network connect 网桥名 容器名

示例:

[root@zutuanxue ~]# docker network connect docker1 centos1

发现 centos1 容器多了一块网卡,使用的正是 docker1 的网段:

[root@zutuanxue ~]# docker exec centos1 ifconfigeth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500        inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255        ether 02:42:ac:11:00:02  txqueuelen 0  (Ethernet)        RX packets 8  bytes 656 (656.0 B)        RX errors 0  dropped 0  overruns 0  frame 0        TX packets 0  bytes 0 (0.0 B)        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500        inet 192.168.1.2  netmask 255.255.255.0  broadcast 192.168.1.255        ether 02:42:c0:a8:01:02  txqueuelen 0  (Ethernet)        RX packets 16  bytes 1312 (1.2 KiB)        RX errors 0  dropped 0  overruns 0  frame 0        TX packets 0  bytes 0 (0.0 B)        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536        inet 127.0.0.1  netmask 255.0.0.0        loop  txqueuelen 1000  (Local Loopback)        RX packets 0  bytes 0 (0.0 B)        RX errors 0  dropped 0  overruns 0  frame 0        TX packets 0  bytes 0 (0.0 B)        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

# 7. 容器断开网桥

docker network disconnect 网桥名 容器名

# 常见问题合集

# 常见问题一:使用改名后的新网桥的容器可能无法解析域名原因:没有配置新网桥的 DNS

解决方法:为容器手动配置一个 DNS 地址即可

# 常见问题二:Networking will not work[root@zutuanxue ~]# docker run -d --network docker100 --name centos4 baishuming2020/centos_nginxWARNING: IPv4 forwarding is disabled. Networking will not work.67f2c276123c993cd66b9d7a99ba22402331a13f9ea8817e57324a934896b805

解决方案: 

1. 打开转发[root@zutuanxue ~]# echo "net.ipv4.ip_forward=1" >>  /usr/lib/sysctl.d/00-system.conf

2. 重启网络[root@zutuanxue ~]# systemctl restart network

# 四、Docker 不同主机间容器通信

# 1. macvlan

在 Docker 中,macvlan 是众多 Docker 网络模型中的一种,并且是一种跨主机的网络模型,作为一种驱动启用,Docker macvlan 只支持 bridge 模式。

# macvlan 需要一块独立的网卡来进行使用,所以我们需要新添加一块网卡docker network create -d macvlan --subnet=172.16.10.0/24 --gateway=172.16.10.1  -o parent=ens224  mtacvlan-1# -o parent=网卡名称  指定用来给 macvlan 网络使用的物理网卡# 注意,要在所有需要运行 macvlan 的主机上执行这条命令,但是要记得更改网关的地址,避免造成 IP 冲突

# 2. overlay

在 Docker 中,overlay 是众多 Docker 网络模型中的一种,并且是一种跨主机的全局网络模型,有一个数据库专门的来存储网络分配信息,避免 IP 冲突,同时内部还有一个小型的 DNS 我们可以直接通过主机名进行访问。

# 1. consul 服务端:
docker run -itd -h consul --name consul --restart=always -p 8500:8500 progrium/consul -server -bootstrap

-h 				主机名
–name 			容器名
–restart=always 重启策略
progrium/consul 镜像名称
-server 		以服务节点启动
-bootstrap		预期的启动节点数:自举

# 2. 在浏览器内输入 IP地址+端口号 可以看到 web 页面

# 3. 在所有主机上编辑 daemon.json 文件:
{
"hosts": ["tcp://0.0.0.0:2375","unix:///var/run/docker.sock"], 监听相关端口
"cluster-store":"consul://192.168.1.150:8500",		   集群的主机地址
"cluster-advertise":"192.168.1.150:2375”		宣告自己的地址 
}

# 4. 重启 docker 服务

# 5. 创建 overlay 网络(全局网络):一台主机上创建自动同步
	docker network create -d overlay overlay-1

# 6. 启动容器测试:
	docker run -it --name docker-1 --network=overlay-1 centos /bin/bash
	docker run -it --name docker-2 --network=overlay-1 centos /bin/bash

# 7. 验证:ping docker-1

# 常见问题合集:

# 场景问题一:各容器内分配的ip之间相互ping不通
- 原因:可能由于防火墙问题引起的,默认 forward 链是d rop状 态,需要打开才可以。

- 解决方案:
执行下面操作,保证 `INPUT`  `FORWARD` 链都是 `ACCEPT` 状态

清除其他规则
[root@zutuanxue_node1 ~]# iptables -P INPUT ACCEPT
[root@zutuanxue_node1 ~]# iptables -P FORWARD ACCEPT
[root@zutuanxue_node1 ~]# iptables -F
[root@zutuanxue_node1 ~]# iptables -L -n

[root@zutuanxue_node2 ~]# iptables -P INPUT ACCEPT
[root@zutuanxue_node2 ~]# iptables -P FORWARD ACCEPT
[root@zutuanxue_node2 ~]# iptables -F
[root@zutuanxue_node2 ~]# iptables -L -n
上次更新: 12/8/2021, 10:11:56 AM