Docker网络

通过容器名称互联:

即在同一个宿主机上的容器之间可以通过自定义的容器名称相互访问,比如一
个业务前端静态页面是使用 nginx,动态页面使用的是 tomcat,由于容器在启动
的时候其内部 IP 地址是 DHCP 随机分配的,所以如果通过内部访问的话,自定
义名称是相对比较固定的,因此比较适用于此场景。

通过自定义容器别名互联:

上一步骤中,自定义的容器名称可能后期会发生变化,那么一旦名称发生变化,
程序之间也要随之发生变化,比如程序通过容器名称进行服务调用,但是容器名
称发生变化之后再使用之前的名称肯定是无法成功调用,每次都进行更改的话又
比较麻烦,因此可以使用自定义别名的方式解决,即容器名称可以随意更,只要
不更改别名即可,具体如下:
命令格式:
docker run -d --name 新容器名称 --link 目标容器名称:自定义的名称 -p 本
地端口:容器端口 镜像名称 shell 命令

docker 网络类型:

Docker 的网络使用 docker network ls 命令看到有三种类型,下面将介绍每一种类
型的具体工作方式:
Bridge 模式,使用参数 –net=bridge 指定,不指定默认就是 bridge 模式。

查看当前 docke 的网卡信息:

[root@ubuntu-1804 ~]# docker network list
NETWORK ID          NAME                DRIVER              SCOPE
4e0e62dec3e5        bridge              bridge              local
87b448b70501        host                host                local
e1ef972a5715        none                null                local

Bridge:#桥接,使用自定义 IP
Host:#不获取 IP 直接使用物理机 IP,并监听物理机 IP 监听端口
None: #没有网络

Host 模式:

Host 模式,使用参数 –net=host 指定。
启动的容器如果指定了使用 host 模式,那么新创建的容器不会创建自己的虚拟
网卡,而是直接使用宿主机的网卡和 IP 地址,因此在容器里面查看到的 IP 信息
就是宿主机的信息,访问容器的时候直接使用宿主机 IP+容器端口即可,不过容
器的其他资源们必须文件系统、系统进程等还是和宿主机保持隔离。
此模式的网络性能最高,但是各容器之间端口不能相同,适用于运行容器端口比
较固定的业务。
为避免端口冲突,先删除所有的容器:

范例:启动一个新容器,并指定网络模式为 host

[root@ubuntu-1804 ~]# docker run -itd --rm -p 80:80 --net=host nginx-18:v1
WARNING: Published ports are discarded when using host network mode
5d6517ef4d89a46f12737bfca85872e3936180f9238fd21fb9228c54075aa494
# 看到的都是跟宿主机一样的
[root@ubuntu-1804 ~]# docker exec -it 5d6517ef4d89 bash

Host 模式不支持端口映射,当指定端口映射的时候会提示如下警告信息:
使用主机网络模式时,将丢弃已指定的端口:

none 模式:

None 模式,使用参数 –net=none 指定
在使用 none 模式后,Docker 容器不会进行任何网络配置,其没有网卡、没有
IP 也没有路由,因此默认无法与外界通信,需要手动添加网卡配置 IP 等,所以
极少使用,

命令使用方式:

[root@ubuntu-1804 ~]# docker run -itd --rm -p 80:80 --net=none nginx-18:v1
d4de190ff4b3657b2390fc732283b88e02e53abe0edb2e34a6a5380c4fa61b69
[root@ubuntu-1804 ~]# docker exec -it d4de190ff4b3 bash

Container 模式:

Container 模式,使用参数 –net=container:名称或 ID 指定。
使用此模式创建的容器需指定和一个已经存在的容器共享一个网络,而不是和宿
主机共享网,新创建的容器不会创建自己的网卡也不会配置自己的 IP,而是和一
个已经存在的被指定的容器东西 IP 和端口范围,因此这个容器的端口不能和被
指定的端口冲突,除了网络之外的文件系统、进程信息等仍然保持相互隔离,两
个容器的进程可以通过 lo 网卡及容器 IP 进行通信。

[root@ubuntu-1804 ~]# docker run -it -d --name nginx-web1 -p 80:80 --net=bridge nginx-18:v1
8c299069a8ca317e2c755ea5ed66913cf880bb0426f826850bae88f5dd80a4eb
[root@ubuntu-1804 ~]# docker run -it -d --name tomcat-web1 --net=container:nginx-web1 tomcat-web:app1
7838fded3e0b337edb250910fd68e3afadcea3b49d5336130d9679b5f9a858e5

#直接使用对方的网络,此方式较少使用

测试

[root@ubuntu-1804 ~]# docker exec -it 8c299069a8ca317e bash
[root@8c299069a8ca /]# ip a
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
66: eth0@if67: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@8c299069a8ca /]# exit
exit
[root@ubuntu-1804 ~]# docker exec -it 7838f bash
[root@8c299069a8ca /]# ip a
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
66: eth0@if67: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@8c299069a8ca /]# exit
exit
[root@ubuntu-1804 ~]#

bridge 模式:

docker 的默认模式即不指定任何模式就是 bridge 模式,也是使用比较多的模式,
此模式创建的容器会为每一个容器分配自己的网络 IP 等信息,并将容器连接到一个虚拟网桥与外界通信。

docker 夸主机互联之简单实现:

夸主机互联是说 A 宿主机的容器可以访问 B 主机上的容器,但是前提是保证各
宿主机之间的网络是可以相互通信的,然后各容器才可以通过宿主机访问到对方
的容器,实现原理是在宿主机做一个网络路由就可以实现 A 宿主机的容器访问 B
主机的容器的目的,复杂的网络或者大型的网络可以使用 google 开源的 k8s 进行互联。

修改各宿主机网段:

Docker 的默认网段是 172.17.0.x/24,而且每个宿主机都是一样的,因此要做路由
的前提就是各个主机的网络不能一致,具体如下:
问避免影响,先在各服务器删除之前穿件的所有容器。

服务器 A 更改网段:

[root@ubuntu-1804 ~]# vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --bip=10.10.0.1/24  # 不能写网段。是写网关

重启 docker 服务并验证网卡:

[root@ubuntu-1804 ~]# systemctl daemon-reload
[root@ubuntu-1804 ~]# systemctl restart docker

验证网卡

[root@ubuntu-1804 ~]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 10.10.0.1  netmask 255.255.255.0  broadcast 10.10.0.255
        inet6 fe80::42:5aff:fe3f:e183  prefixlen 64  scopeid 0x20<link>
        ether 02:42:5a:3f:e1:83  txqueuelen 0  (Ethernet)
        RX packets 52093  bytes 3221087 (3.2 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 109844  bytes 219160324 (219.1 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0


服务器 B 更改网段:

[root@ubuntu-1804 ~]# vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --bip=10.20.0.1/24  # 不能写网段。是写网关

重启 docker 服务并验证网卡:

[root@ubuntu-1804 ~]# systemctl daemon-reload
[root@ubuntu-1804 ~]# systemctl restart docker

验证网卡

[root@ubuntu-1804 ~]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 10.20.0.1  netmask 255.255.255.0  broadcast 10.20.0.255
        inet6 fe80::42:fdff:fe5e:d828  prefixlen 64  scopeid 0x20<link>
        ether 02:42:fd:5e:d8:28  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5  bytes 446 (446.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

在两个宿主机分别启动一个容器:

# app1
[root@ubuntu-1804 ~]# docker run -itd -p 80:80 nginx-18:v1
7924f12e74b173e90ae4f1908c8a74632696c15b56240a40fc245aed518e6877
[root@ubuntu-1804 ~]# docker exec -it 7924f bash
[root@7924f12e74b1 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.10.0.2  netmask 255.255.255.0  broadcast 10.10.0.255
        ether 02:42:0a:0a:00:02  txqueuelen 0  (Ethernet)
        RX packets 10  bytes 836 (836.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


# app2
[root@ubuntu-1804 ~]# docker run -itd harbor.longxuan.vip/m44/tomcat-web:app2
8e7d026d6ebbbf67e61de87acbce6362f6c0c6ee7d44eab347fc037eef2f677e
[root@ubuntu-1804 ~]# docker exec -it 8e7d0 bash
[root@8e7d026d6ebb /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.20.0.2  netmask 255.255.255.0  broadcast 10.20.0.255
        ether 02:42:0a:14:00:02  txqueuelen 0  (Ethernet)
        RX packets 10  bytes 836 (836.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

测试:正常能ping通外网比如baidu.com,但是不能ping通另一台docker容器的ip

[root@cb163feafbac /]# ping www.baidu.com
PING www.a.shifen.com (110.242.68.3) 56(84) bytes of data.
64 bytes from 110.242.68.3 (110.242.68.3): icmp_seq=1 ttl=52 time=11.5 ms

添加静态路由:

各宿主机添加静态路由,网关指向对方的 IP

app1 添加静态路由:

[root@ubuntu-1804 ~]# route add -net 10.20.0.0/24 gw 172.18.8.149

[root@ubuntu-1804 ~]# iptables -A FORWARD -s 172.18.0.0/16 -j ACCEPT

app2 添加静态路由:

[root@ubuntu-1804 ~]# route add -net 10.10.0.0/24 gw 172.18.8.139

[root@ubuntu-1804 ~]# iptables -A FORWARD -s 172.18.0.0/16 -j ACCEPT

在容器里面的Nginx添加配置文件代理到另外一台Tomcat

[root@7924f12e74b1 /]# vim /apps/nginx/conf/nginx.conf

location /myapp {
            proxy_pass http://10.20.0.2:8080;  # 另外的容器主机IP地址
        }

访问测试
http://172.18.8.139/myapp/

在app2 的Tomcat容器查看日志看到如下信息:
[root@8e7d026d6ebb /]# tail -f /apps/tomcat/logs/localhost_access_log.2021-07-20.txt
172.18.8.139 - - [20/Jul/2021:14:37:38 +0800] "GET /myapp/ HTTP/1.0" 200 18
172.18.8.139 - - [20/Jul/2021:14:37:56 +0800] "GET /myapp HTTP/1.0" 302 -
172.18.8.139 - - [20/Jul/2021:14:42:57 +0800] "GET /myapp/ HTTP/1.0" 304 -
172.18.8.139 - - [20/Jul/2021:14:42:57 +0800] "GET /myapp/ HTTP/1.0" 304 -
172.18.8.139 - - [20/Jul/2021:14:42:57 +0800] "GET /myapp/ HTTP/1.0" 304 -

tcpdump抓包测试

# 在容器ping另外一个容器的主机IP地址
[root@7924f12e74b1 /]# ping 10.20.0.2
PING 10.20.0.2 (10.20.0.2) 56(84) bytes of data.
64 bytes from 10.20.0.2: icmp_seq=1 ttl=62 time=0.533 ms
64 bytes from 10.20.0.2: icmp_seq=2 ttl=62 time=0.541 ms
64 bytes from 10.20.0.2: icmp_seq=3 ttl=62 time=0.549 ms

# 看到信息如下:
root@ubuntu-1804:~# tcpdump -i eth0 -vnn icmp
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
06:48:57.290901 IP (tos 0x0, ttl 63, id 43688, offset 0, flags [DF], proto ICMP (1), length 84)
    172.18.8.139 > 10.20.0.2: ICMP echo request, id 59, seq 1, length 64
06:48:57.291092 IP (tos 0x0, ttl 63, id 63931, offset 0, flags [none], proto ICMP (1), length 84)
    10.20.0.2 > 172.18.8.139: ICMP echo reply, id 59, seq 1, length 64
06:48:58.308464 IP (tos 0x0, ttl 63, id 43829, offset 0, flags [DF], proto ICMP (1), length 84)
    172.18.8.139 > 10.20.0.2: ICMP echo request, id 59, seq 2, length 64
06:48:58.308602 IP (tos 0x0, ttl 63, id 64040, offset 0, flags [none], proto ICMP (1), length 84)
    10.20.0.2 > 172.18.8.139: ICMP echo reply, id 59, seq 2, length 64
06:48:59.332448 IP (tos 0x0, ttl 63, id 43956, offset 0, flags [DF], proto ICMP (1), length 84)

两个宿主机的路由表

# app1
root@ubuntu-1804:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.18.1.1      0.0.0.0         UG    0      0        0 eth0
10.10.0.0       0.0.0.0         255.255.255.0   U     0      0        0 docker0
10.20.0.0       172.18.8.149    255.255.255.0   UG    0      0        0 eth0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0

# app2
root@ubuntu-1804:~# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.18.1.1      0.0.0.0         UG    0      0        0 eth0
10.10.0.0       172.18.8.139    255.255.255.0   UG    0      0        0 eth0
10.20.0.0       0.0.0.0         255.255.255.0   U     0      0        0 docker0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth0

创建自定义网络:

可以基于 docker 命令创建自定义网络,自定义网络可以自定义 IP 地范围和网关等信息。

创建自定义 docker 网络

# 帮助
[root@ubuntu-1804 ~]# docker network create –help

创建

[root@ubuntu-1804 ~]# docker network create -d bridge --subnet 10.100.0.0/24 --gateway 10.100.0.1 longxuan-net  # 自定义网络名称

验证

[root@ubuntu-1804 ~]# docker network list
NETWORK ID          NAME                DRIVER              SCOPE
45410b39ca9b        bridge              bridge              local
87b448b70501        host                host                local
f14531f6983b        longxuan-net        bridge              local
e1ef972a5715        none                null                local

创建不同网络的容器测试通信

使用自定义网络创建容器

[root@ubuntu-1804 ~]# docker run -it -p 8081:8080 --name longxuan-net-test --net=longxuan-net tomcat-web:app1 bash
[root@8d61a1045048 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.100.0.2  netmask 255.255.255.0  broadcast 10.100.0.255
        ether 02:42:0a:64:00:02  txqueuelen 0  (Ethernet)
        RX packets 11  bytes 962 (962.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

测试ping 外网

[root@8d61a1045048 /]# ping www.baidu.com
PING www.a.shifen.com (110.242.68.4) 56(84) bytes of data.
64 bytes from 110.242.68.4 (110.242.68.4): icmp_seq=1 ttl=52 time=12.0 ms
64 bytes from 110.242.68.4 (110.242.68.4): icmp_seq=2 ttl=52 time=13.2 ms
64 bytes from 110.242.68.4 (110.242.68.4): icmp_seq=3 ttl=52 time=10.4 ms

如何与使用默认网络的容器通信:

现在有一个 docker0(10.10.0.0/24)网络一个自定义的 longxuan-net(10.100.0.0/24)
网络,每个网络上分别运行了不同数量的容器,那么怎么才能让位于不同网络的容器可以相互通信呢?

[root@ubuntu-1804 ~]# iptables-save
[root@ubuntu-1804 ~]# iptables-save > iptables-bak.sh

# 进入iptables-bak.sh把有DROP
[root@ubuntu-1804 ~]# vim iptables-bak.sh
-A DOCKER-ISOLATION-STAGE-2 -o br-f14531f6983b -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
这两行要么注释掉,要么把 -j DROP 改成 -j ACCEPT

# 重新导入 iptables规则 并验证通信:
[root@ubuntu-1804 ~]# iptables-restore < iptables-bak.sh

验证

[root@ubuntu-1804 ~]# docker run -it -p 8080:8080 --name longxuan-net-test --net=longxuan-net tomcat-web:app1 bash
[root@a7929a9b0aca /]# ip a
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
81: eth0@if82: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:0a:64:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.100.0.2/24 brd 10.100.0.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@a7929a9b0aca /]# ping 10.10.0.2
PING 10.10.0.2 (10.10.0.2) 56(84) bytes of data.
64 bytes from 10.10.0.2: icmp_seq=1 ttl=63 time=0.248 ms
64 bytes from 10.10.0.2: icmp_seq=2 ttl=63 time=0.141 ms
posted @ 2021-08-20 20:45  空白的旋律  阅读(85)  评论(0编辑  收藏  举报