0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Docker容器的四种网络模式

jf_ro2CN3Fa 来源:博客园 作者:博客园 2022-10-17 14:53 次阅读

docker 容器网络

Docker 在安装后自动提供 3 种网络,可以使用 docker network ls 命令查看

[root@localhost~]#dockernetworkls
NETWORKIDNAMEDRIVERSCOPE
cd97bb997b84bridgebridgelocal
0a04824fc9b6hosthostlocal
4dcb8fbdb599nonenulllocal

Docker 使用 Linux 桥接,在宿主机虚拟一个 Docker 容器网桥(docker0),Docker 启动一个容器时会根据 Docker 网桥的网段分配给容器一个 IP 地址,称为 Container-IP,同时 Docker 网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的 Container-IP 直接通信

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

项目地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro

视频教程:https://doc.iocoder.cn/video/

docker 的 4 种网络模式

网络模式 配置 说明
host --network host 容器和宿主机共享Network namespace
container --network container:NAME_OR_ID 容器和另外一个容器共享Network namespace
none --network none 容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair 和网桥连接,配置IP等
bridge --network bridge默认模式

d1760a14-4cfe-11ed-a3b6-dac502259ad0.png

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

项目地址:https://gitee.com/zhijiantianya/yudao-cloud

视频教程:https://doc.iocoder.cn/video/

bridge 模式

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

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

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

bridge 模式如下图所示:

d2214a28-4cfe-11ed-a3b6-dac502259ad0.png

假设上图的 docker2 中运行了一个 nginx,大家来想几个问题:

同主机间两个容器间是否可以直接通信?比如在 docker1 上能不能直接访问到 docker2 的 nginx 站点?

在宿主机上能否直接访问到 docker2 的 nginx 站点?

在另一台主机上如何访问 node1 上的这个 nginx 站点呢?DNAT 发布?

Docker 网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接 Container-IP 访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即 docker run 创建容器时候通过 -p 或 -P 参数来启用,访问容器的时候就通过[宿主机 IP]:[容器端口]访问容器。

container 模式

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

container 模式如下图所示:

d24ab1f6-4cfe-11ed-a3b6-dac502259ad0.png

host 模式

如果启动容器的时候使用 host 模式,那么这个容器将不会获得一个独立的 Network Namespace,而是和宿主机共用一个 Network Namespace。容器将不会虚拟出自己的网卡,配置自己的 IP 等,而是使用宿主机的 IP 和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。

使用 host 模式的容器可以直接使用宿主机的 IP 地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行 NAT,host 最大的优势就是网络性能比较好,但是 docker host 上已经使用的端口就不能再用了,网络的隔离性不好。

Host 模式如下图所示:

d2599220-4cfe-11ed-a3b6-dac502259ad0.png

none 模式

使用 none 模式,Docker 容器拥有自己的 Network Namespace,但是,并不为 Docker 容器进行任何网络配置。也就是说,这个 Docker 容器没有网卡、IP、路由等信息。需要我们自己为 Docker 容器添加网卡、配置 IP 等。

这种网络模式下容器只有 lo 回环网络,没有其他网卡。none 模式可以在容器创建时通过--network none 来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。

应用场景

启动一个容器处理数据,比如转换数据格式

一些后台的计算和处理任务

none 模式如下图所示:

d28c8b94-4cfe-11ed-a3b6-dac502259ad0.png

dockernetworkinspectbridge#查看bridge网络的详细配置

docker 容器网络配置

Linux 内核实现名称空间的创建

ip netns 命令

可以借助 ip netns 命令来完成对 Network Namespace 的各种操作。ip netns 命令来自于 iproute 安装包,一般系统会默认安装,如果没有的话,请自行安装。

注意:ip netns 命令修改网络配置时需要 sudo 权限。

可以通过 ip netns 命令完成对 Network Namespace 的相关操作,可以通过 ip netns help 查看命令帮助信息:

[root@localhost~]#ipnetnshelp
Usage:ipnetnslist
ipnetnsaddNAME
ipnetnssetNAMENETNSID
ip[-all]netnsdelete[NAME]
ipnetnsidentify[PID]
ipnetnspidsNAME
ip[-all]netnsexec[NAME]cmd...
ipnetnsmonitor
ipnetnslist-id

默认情况下,Linux 系统中是没有任何 Network Namespace 的,所以 ip netns list 命令不会返回任何信息。

创建 Network Namespace

通过命令创建一个名为 ns0 的命名空间:

[root@localhost~]#ipnetnslist
[root@localhost~]#ipnetnsaddns0
[root@localhost~]#ipnetnslist
ns0

新创建的 Network Namespace 会出现在/var/run/netns/目录下。如果相同名字的 namespace 已经存在,命令会报 Cannot create namespace file "/var/run/netns/ns0": File exists 的错误。

[root@localhost~]#ls/var/run/netns/
ns0
[root@localhost~]#ipnetnsaddns0
Cannotcreatenamespacefile"/var/run/netns/ns0":Fileexists

对于每个 Network Namespace 来说,它会有自己独立的网卡、路由表、ARP 表、iptables 等和网络相关的资源。

操作 Network Namespace

ip 命令提供了 ip netns exec 子命令可以在对应的 Network Namespace 中执行命令。

查看新创建 Network Namespace 的网卡信息

[root@localhost~]#ipnetnsexecns0ipaddr
1:lo:mtu65536qdiscnoopstateDOWNgroupdefaultqlen1000
link/loopback00:00:00:00:00:00brd00:00:00:00:00:00

可以看到,新创建的 Network Namespace 中会默认创建一个 lo 回环网卡,此时网卡处于关闭状态。此时,尝试去 ping 该 lo 回环网卡,会提示 Network is unreachable

[root@localhost~]#ipnetnsexecns0ping127.0.0.1
connect:Networkisunreachable

127.0.0.1是默认回环网卡

通过下面的命令启用 lo 回环网卡:

[root@localhost~]#ipnetnsexecns0iplinksetloup
[root@localhost~]#ipnetnsexecns0ping127.0.0.1
PING127.0.0.1(127.0.0.1)56(84)bytesofdata.
64bytesfrom127.0.0.1:icmp_seq=1ttl=64time=0.029ms
64bytesfrom127.0.0.1:icmp_seq=2ttl=64time=0.029ms
^C
---127.0.0.1pingstatistics---
2packetstransmitted,2received,0%packetloss,time1036ms
rttmin/avg/max/mdev=0.029/0.029/0.029/0.000ms

转移设备

我们可以在不同的 Network Namespace 之间转移设备(如 veth)。由于一个设备只能属于一个 Network Namespace ,所以转移后在这个 Network Namespace 内就看不到这个设备了。

其中,veth 设备属于可转移设备,而很多其它设备(如 lo、vxlan、ppp、bridge 等)是不可以转移的。

veth pair

veth pair 全称是 Virtual Ethernet Pair,是一个成对的端口,所有从这对端口一 端进入的数据包都将从另一端出来,反之也是一样。

引入 veth pair 是为了在不同的 Network Namespace 直接进行通信,利用它可以直接将两个 Network Namespace 连接起来。

d2cb7296-4cfe-11ed-a3b6-dac502259ad0.png

创建 veth pair

[root@localhost~]#iplinkaddtypeveth
[root@localhost~]#ipa

4:veth0@veth1:mtu1500qdiscnoopstateDOWNgroupdefaultqlen1000
link/ether0ae2:2d:37:fbbrdffffff:ff
5:veth1@veth0:mtu1500qdiscnoopstateDOWNgroupdefaultqlen1000
link/ether5e:7e594fbrdffffff:ff

可以看到,此时系统中新增了一对 veth pair,将 veth0 和 veth1 两个虚拟网卡连接了起来,此时这对 veth pair 处于”未启用“状态。

实现 Network Namespace 间通信

下面我们利用 veth pair 实现两个不同的 Network Namespace 之间的通信。刚才我们已经创建了一个名为 ns0 的 Network Namespace,下面再创建一个信息 Network Namespace,命名为 ns1

[root@localhost~]#ipnetnsaddns1
[root@localhost~]#ipnetnslist
ns1
ns0

然后我们将 veth0 加入到 ns0,将 veth1 加入到 ns1

[root@localhost~]#iplinksetveth0netnsns0
[root@localhost~]#iplinksetveth1netnsns1

然后我们分别为这对 veth pair 配置上 ip 地址,并启用它们

[root@localhost~]#ipnetnsexecns0iplinksetveth0up
[root@localhost~]#ipnetnsexecns0ipaddradd192.0.0.1/24devveth0
[root@localhost~]#ipnetnsexecns1iplinksetveth1up
[root@localhost~]#ipnetnsexecns1ipaddradd192.0.0.2/24devveth1

查看这对 veth pair 的状态

[root@localhost~]#ipnetnsexecns0ipa
1:lo:mtu65536qdiscnoqueuestateUNKNOWNgroupdefaultqlen1000
link/loopback00:00:00:00:00:00brd00:00:00:00:00:00
inet127.0.0.1/8scopehostlo
valid_lftforeverpreferred_lftforever
inet6::1/128scopehost
valid_lftforeverpreferred_lftforever
4:veth0@if5:mtu1500qdiscnoqueuestateUPgroupdefaultqlen1000
link/ether0ae2:2d:37:fbbrdffffff:fflink-netnsns1
inet192.0.0.1/24scopeglobalveth0
valid_lftforeverpreferred_lftforever
inet6fe80::8f4fe2d:37fb/64scopelink
valid_lftforeverpreferred_lftforever
[root@localhost~]#ipnetnsexecns1ipa
1:lo:mtu65536qdiscnoopstateDOWNgroupdefaultqlen1000
link/loopback00:00:00:00:00:00brd00:00:00:00:00:00
5:veth1@if4:mtu1500qdiscnoqueuestateUPgroupdefaultqlen1000
link/ether5e:7e594fbrdffffff:fflink-netnsns0
inet192.0.0.2/24scopeglobalveth1
valid_lftforeverpreferred_lftforever
inet6fe80::5c7efe59:f04f/64scopelink
valid_lftforeverpreferred_lftforever

从上面可以看出,我们已经成功启用了这个 veth pair,并为每个 veth 设备分配了对应的 ip 地址。我们尝试在 ns1 中访问 ns0 中的 ip 地址

[root@localhost~]#ipnetnsexecns1ping192.0.0.1
PING192.0.0.1(192.0.0.1)56(84)bytesofdata.
64bytesfrom192.0.0.1:icmp_seq=1ttl=64time=0.033ms
64bytesfrom192.0.0.1:icmp_seq=2ttl=64time=0.041ms
^C
---192.0.0.1pingstatistics---
2packetstransmitted,2received,0%packetloss,time1001ms
rttmin/avg/max/mdev=0.033/0.037/0.041/0.004ms
[root@localhost~]#ipnetnsexecns0ping192.0.0.2
PING192.0.0.2(192.0.0.2)56(84)bytesofdata.
64bytesfrom192.0.0.2:icmp_seq=1ttl=64time=0.025ms
64bytesfrom192.0.0.2:icmp_seq=2ttl=64time=0.025ms
^C
---192.0.0.2pingstatistics---
2packetstransmitted,2received,0%packetloss,time1038ms
rttmin/avg/max/mdev=0.025/0.025/0.025/0.000ms

可以看到,veth pair 成功实现了两个不同 Network Namespace 之间的网络交互。

四种网络模式配置

bridge 模式配置

[root@localhost~]#dockerrun-it--nameti--rmbusybox
/#ifconfig
eth0Linkencap:EthernetHWaddr02:4211:00:02
inetaddr:172.17.0.2Bcast:172.17.255.255Mask:255.255.0.0
UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1
RXpackets:12errors:0dropped:0overruns:0frame:0
TXpackets:0errors:0dropped:0overruns:0carrier:0
collisions:0txqueuelen:0
RXbytes:1032(1.0KiB)TXbytes:0(0.0B)

loLinkencap:LocalLoopback
inetaddr:127.0.0.1Mask:255.0.0.0
UPLOOPBACKRUNNINGMTU:65536Metric:1
RXpackets:0errors:0dropped:0overruns:0frame:0
TXpackets:0errors:0dropped:0overruns:0carrier:0
collisions:0txqueuelen:1000
RXbytes:0(0.0B)TXbytes:0(0.0B)

在创建容器时添加--network bridge 与不加--network 选项效果是一致的

[root@localhost~]#dockerrun-it--namet1--networkbridge--rmbusybox
/#ifconfig
eth0Linkencap:EthernetHWaddr02:4211:00:02
inetaddr:172.17.0.2Bcast:172.17.255.255Mask:255.255.0.0
UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1
RXpackets:8errors:0dropped:0overruns:0frame:0
TXpackets:0errors:0dropped:0overruns:0carrier:0
collisions:0txqueuelen:0
RXbytes:696(696.0B)TXbytes:0(0.0B)

loLinkencap:LocalLoopback
inetaddr:127.0.0.1Mask:255.0.0.0
UPLOOPBACKRUNNINGMTU:65536Metric:1
RXpackets:0errors:0dropped:0overruns:0frame:0
TXpackets:0errors:0dropped:0overruns:0carrier:0
collisions:0txqueuelen:1000
RXbytes:0(0.0B)TXbytes:0(0.0B)

none 模式配置

[root@localhost~]#dockerrun-it--namet1--networknone--rmbusybox
/#ifconfig-a
loLinkencap:LocalLoopback
inetaddr:127.0.0.1Mask:255.0.0.0
UPLOOPBACKRUNNINGMTU:65536Metric:1
RXpackets:0errors:0dropped:0overruns:0frame:0
TXpackets:0errors:0dropped:0overruns:0carrier:0
collisions:0txqueuelen:1000
RXbytes:0(0.0B)TXbytes:0(0.0B)

container 模式配置

启动第一个容器

[root@localhost~]#dockerrun-dit--nameb3busybox
af5ba32f990ebf5a46d7ecaf1eec67f1712bbef6ad7df37d52b7a8a498a592a0

[root@localhost~]#dockerexec-itb3/bin/sh
/#ifconfig
eth0Linkencap:EthernetHWaddr02:4211:00:02
inetaddr:172.17.0.2Bcast:172.17.255.255Mask:255.255.0.0
UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1
RXpackets:11errors:0dropped:0overruns:0frame:0
TXpackets:0errors:0dropped:0overruns:0carrier:0
collisions:0txqueuelen:0
RXbytes:906(906.0B)TXbytes:0(0.0B)

启动第二个容器

[root@localhost~]#dockerrun-it--nameb2--rmbusybox
/#ifconfig
eth0Linkencap:EthernetHWaddr02:4211:00:03
inetaddr:172.17.0.3Bcast:172.17.255.255Mask:255.255.0.0
UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1
RXpackets:6errors:0dropped:0overruns:0frame:0
TXpackets:0errors:0dropped:0overruns:0carrier:0
collisions:0txqueuelen:0
RXbytes:516(516.0B)TXbytes:0(0.0B)

可以看到名为 b2 的容器 IP 地址是 10.0.0.3,与第一个容器的 IP 地址不是一样的,也就是说并没有共享网络,此时如果我们将第二个容器的启动方式改变一下,就可以使名为 b2 的容器 IP 与 B3 容器 IP 一致,也即共享 IP,但不共享文件系统。

[root@localhost~]#dockerrun-it--nameb2--rm--networkcontainer:b3busybox
/#ifconfig
eth0Linkencap:EthernetHWaddr02:4211:00:02
inetaddr:172.17.0.2Bcast:172.17.255.255Mask:255.255.0.0
UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1
RXpackets:14errors:0dropped:0overruns:0frame:0
TXpackets:0errors:0dropped:0overruns:0carrier:0
collisions:0txqueuelen:0
RXbytes:1116(1.0KiB)TXbytes:0(0.0B)

此时我们在b1容器上创建一个目录

/#mkdir/tmp/data
/#ls/tmp
data

到 b2 容器上检查/tmp 目录会发现并没有这个目录,因为文件系统是处于隔离状态,仅仅是共享了网络而已。

在 b2 容器上部署一个站点

/#echo'helloworld'>/tmp/index.html
/#ls/tmp
index.html
/#httpd-h/tmp
/#netstat-antl
ActiveInternetconnections(serversandestablished)
ProtoRecv-QSend-QLocalAddressForeignAddressState
tcp00:::80:::*LISTEN

在 b1 容器上用本地地址去访问此站点

/#wget-O--q172.17.0.2:80
helloworld

host 模式配置

启动容器时直接指明模式为 host

[root@localhost~]#dockerrun-it--nameb2--rm--networkhostbusybox
/#ifconfig
docker0Linkencap:EthernetHWaddr02:427F:8E:2C
inetaddr:172.17.0.1Bcast:172.17.255.255Mask:255.255.0.0
inet6addr:fe80::42fe7f:8e2c/64Scope:Link
UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1
RXpackets:3errors:0dropped:0overruns:0frame:0
TXpackets:20errors:0dropped:0overruns:0carrier:0
collisions:0txqueuelen:0
RXbytes:116(116.0B)TXbytes:1664(1.6KiB)

ens33Linkencap:EthernetHWaddr00:0C:29:95:19:47
inetaddr:192.168.203.138Bcast:192.168.203.255Mask:255.255.255.0
inet6addr:fe80::2e61:1ea33d9b/64Scope:Link
UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1
RXpackets:9626errors:0dropped:0overruns:0frame:0
TXpackets:3950errors:0dropped:0overruns:0carrier:0
collisions:0txqueuelen:1000
RXbytes:3779562(3.6MiB)TXbytes:362386(353.8KiB)

loLinkencap:LocalLoopback
inetaddr:127.0.0.1Mask:255.0.0.0
inet6addr:::1/128Scope:Host
UPLOOPBACKRUNNINGMTU:65536Metric:1
RXpackets:0errors:0dropped:0overruns:0frame:0
TXpackets:0errors:0dropped:0overruns:0carrier:0
collisions:0txqueuelen:1000
RXbytes:0(0.0B)TXbytes:0(0.0B)

veth09ee47eLinkencap:EthernetHWaddrB2:10:53:7B:66:AE
inet6addr:fe80:53ff66ae/64Scope:Link
UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1
RXpackets:3errors:0dropped:0overruns:0frame:0
TXpackets:19errors:0dropped:0overruns:0carrier:0
collisions:0txqueuelen:0
RXbytes:158(158.0B)TXbytes:1394(1.3KiB)

此时如果我们在这个容器中启动一个 http 站点,我们就可以直接用宿主机的 IP 直接在浏览器中访问这个容器中的站点了。

容器的常用操作

查看容器的主机名

[root@localhost~]#dockerrun-it--namet1--networkbridge--rmbusybox
/#hostname
48cb45a0b2e7

在容器启动时注入主机名

[root@localhost~]#dockerrun-it--namet1--networkbridge--hostnameljl--rmbusybox
/#hostname
ljl
/#cat/etc/hosts
127.0.0.1localhost
::1localhostip6-localhostip6-loopback
fe00::0ip6-localnet
ff00::0ip6-mcastprefix
ff02::1ip6-allnodes
ff02::2ip6-allrouters
172.17.0.3ljl
/#cat/etc/resolv.conf
#GeneratedbyNetworkManager
searchlocaldomain
nameserver192.168.203.2
/#pingwww.baidu.com
PINGwww.baidu.com(182.61.200.7):56databytes
64bytesfrom182.61.200.7:seq=0ttl=127time=31.929ms
64bytesfrom182.61.200.7:seq=1ttl=127time=41.062ms
64bytesfrom182.61.200.7:seq=2ttl=127time=31.540ms
^C
---www.baidu.compingstatistics---
3packetstransmitted,3packetsreceived,0%packetloss
round-tripmin/avg/max=31.540/34.843/41.062ms

手动指定容器要使用的 DNS

[root@localhost~]#dockerrun-it--namet1--networkbridge--hostnameljl--dns114.114.114.114--rmbusybox
/#cat/etc/resolv.conf
searchlocaldomain
nameserver114.114.114.114
/#nslookup-type=awww.baidu.com
Server:114.114.114.114
Address:114.114.114.114:53

Non-authoritativeanswer:
www.baidu.comcanonicalname=www.a.shifen.com
Name:www.a.shifen.com
Address:182.61.200.6
Name:www.a.shifen.com
Address:182.61.200.7

手动往/etc/hosts 文件中注入主机名到 IP 地址的映射

[root@localhost~]#dockerrun-it--namet1--networkbridge--hostnameljl--add-hostwww.a.com:1.1.1.1--rmbusybox
/#cat/etc/hosts
127.0.0.1localhost
::1localhostip6-localhostip6-loopback
fe00::0ip6-localnet
ff00::0ip6-mcastprefix
ff02::1ip6-allnodes
ff02::2ip6-allrouters
1.1.1.1www.a.com
172.17.0.3ljl

开放容器端口

执行 docker run 的时候有个-p 选项,可以将容器中的应用端口映射到宿主机中,从而实现让外部主机可以通过访问宿主机的某端口来访问容器内应用的目的。

-p 选项能够使用多次,其所能够暴露的端口必须是容器确实在监听的端口。

-p 选项的使用格式:

-p containerPort

将指定的容器端口映射至主机所有地址的一个动态端口-p hostPort : containerPort

将容器端口 containerPort 映射至指定的主机端口 hostPort

-p ip :: containerPort

将指定的容器端口 containerPort 映射至主机指定 ip 的动态端口

-p ip : hostPort : containerPort

将指定的容器端口 containerPort 映射至主机指定 ip 的端口 hostPort

动态端口指的是随机端口,具体的映射结果可使用 docker port 命令查看。

[root@localhost~]#dockerrun-dit--nameweb1-p192.168.203.138::80httpd
e97bc1774e40132659990090f0e98a308a7f83986610ca89037713e9af8a6b9f
[root@localhost~]#dockerps
CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES
e97bc1774e40httpd"httpd-foreground"6secondsagoUp5seconds192.168.203.138:49153->80/tcpweb1
af5ba32f990ebusybox"sh"48minutesagoUp48minutesb3
[root@localhost~]#ss-antl
StateRecv-QSend-QLocalAddress:PortPeerAddress:PortProcess
LISTEN0128192.168.203.138:491530.0.0.0:*
LISTEN01280.0.0.0:220.0.0.0:*
LISTEN0128[::]:22[::]:*

以上命令执行后会一直占用着前端,我们新开一个终端连接来看一下容器的 80 端口被映射到了宿主机的什么端口上

[root@localhost~]#dockerportweb1
80/tcp->192.168.203.138:49153

由此可见,容器的 80 端口被暴露到了宿主机的 49153 端口上,此时我们在宿主机上访问一下这个端口看是否能访问到容器内的站点

[root@localhost~]#curlhttp://192.168.203.138:49153

Itworks!

iptables 防火墙规则将随容器的创建自动生成,随容器的删除自动删除规则。

[root@localhost~]#iptables-tnat-nvL
ChainPREROUTING(policyACCEPT0packets,0bytes)
pktsbytestargetprotoptinoutsourcedestination
3164DOCKERall--**0.0.0.0/00.0.0.0/0ADDRTYPEmatchdst-typeLOCAL

ChainINPUT(policyACCEPT0packets,0bytes)
pktsbytestargetprotoptinoutsourcedestination

ChainPOSTROUTING(policyACCEPT0packets,0bytes)
pktsbytestargetprotoptinoutsourcedestination
4261MASQUERADEall--*!docker0172.17.0.0/160.0.0.0/0
00MASQUERADEtcp--**172.17.0.3172.17.0.3tcpdpt:80

ChainOUTPUT(policyACCEPT0packets,0bytes)
pktsbytestargetprotoptinoutsourcedestination
2120DOCKERall--**0.0.0.0/0!127.0.0.0/8ADDRTYPEmatchdst-typeLOCAL

ChainDOCKER(2references)
pktsbytestargetprotoptinoutsourcedestination
160RETURNall--docker0*0.0.0.0/00.0.0.0/0
160DNATtcp--!docker0*0.0.0.0/0192.168.203.138tcpdpt:49153to80

将容器端口映射到指定 IP 的随机端口

[root@localhost~]#dockerrun-dit--nameweb1-p192.168.203.138::80httpd

在另一个终端上查看端口映射情况

[root@localhost~]#dockerportweb1
80/tcp->192.168.203.138:49153

自定义 docker0 桥的网络属性信息

自定义 docker0 桥的网络属性信息需要修改/etc/docker/daemon.json 配置文件

[root@localhost~]#cd/etc/docker/
[root@localhostdocker]#vimdaemon.json
[root@localhostdocker]#systemctldaemon-reload
[root@localhostdocker]#systemctlrestartdocker

{
"registry-mirrors":["https://4hygggbu.mirror.aliyuncs.com/"],
"bip":"192.168.1.5/24"
}
EOF

```ruby
[root@localhost~]#vim/lib/systemd/system/docker.service

ExecStart=/usr/bin/dockerd-Hfd://--containerd=/run/containerd/containerd.sock-Htcp://0.0.0.0:2375-Hunix:///var/run/docker.sock
[root@localhost~]#systemctldaemon-reload
[root@localhost~]#systemctlrestartdocker

在客户端上向 dockerd 直接传递“-H|--host”选项指定要控制哪台主机上的 docker 容器

[root@localhost~]#docker-H192.168.203.138:2375ps
CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES
e97bc1774e40httpd"httpd-foreground"30minutesagoUp11seconds192.168.203.138:49153->80/tcpweb1
af5ba32f990ebusybox"sh"AboutanhouragoUp14secondsb3

创建新网络

[root@localhost~]#dockernetworkcreateljl-dbridge
883eda50812bb214c04986ca110dbbcb7600eba8b033f2084cd4d750b0436e12
[root@localhost~]#dockernetworkls
NETWORKIDNAMEDRIVERSCOPE
0c5f4f114c27bridgebridgelocal
8c2d14f1fb82hosthostlocal
883eda50812bljlbridgelocal
85ed12d38815nonenulllocal

创建一个额外的自定义桥,区别于 docker0

[root@localhost~]#dockernetworkcreate-dbridge--subnet"192.168.2.0/24"--gateway"192.168.2.1"br0
af9ba80deb619de3167939ec5b6d6136a45dce90907695a5bc5ed4608d188b99
[root@localhost~]#dockernetworkls
NETWORKIDNAMEDRIVERSCOPE
af9ba80deb61br0bridgelocal
0c5f4f114c27bridgebridgelocal
8c2d14f1fb82hosthostlocal
883eda50812bljlbridgelocal
85ed12d38815nonenulllocal

使用新创建的自定义桥来创建容器:

[root@localhost~]#dockerrun-it--nameb1--networkbr0busybox
/#ifconfig
eth0Linkencap:EthernetHWaddr02C002:02
inetaddr:192.168.2.2Bcast:192.168.2.255Mask:255.255.255.0
UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1
RXpackets:11errors:0dropped:0overruns:0frame:0
TXpackets:0errors:0dropped:0overruns:0carrier:0
collisions:0txqueuelen:0
RXbytes:962(962.0B)TXbytes:0(0.0B)

再创建一个容器,使用默认的 bridge 桥:

[root@localhost~]#dockerrun--nameb2-itbusybox
/#ls
bindevetchomeprocrootsystmpusrvar
/#ifconfig
eth0Linkencap:EthernetHWaddr02C001:03
inetaddr:192.168.1.3Bcast:192.168.1.255Mask:255.255.255.0
UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1
RXpackets:6errors:0dropped:0overruns:0frame:0
TXpackets:0errors:0dropped:0overruns:0carrier:0
collisions:0txqueuelen:0
RXbytes:516(516.0B)TXbytes:0(0.0B)

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 容器
    +关注

    关注

    0

    文章

    494

    浏览量

    22050
  • spring
    +关注

    关注

    0

    文章

    338

    浏览量

    14319
  • Docker
    +关注

    关注

    0

    文章

    456

    浏览量

    11825

原文标题:5 年工作经验,Docker 的几种网络模式都说不清,你敢信?

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    四种不同供电模式的LED拓扑介绍

    本文中,小编将为大家介绍四种在LED供电当中经常使用的四种拓扑结构。感兴趣的朋友快来看一看吧。 首先需要从了解转换器的最小及最大输出电压入手。这只是将所有LED正向压降与传感电阻器电压相加的总数
    发表于 10-10 15:07

    STM32芯片GPIO的四种输入模式四种输出模式

    STM32芯片的GPIO一共有8配置模式,对8模式的理解如下1.四种输入模式上拉输入:在默认
    发表于 05-21 07:55

    docker四种网络模式

    docker网络模式
    发表于 10-16 08:11

    单片机四种输入模式

    单片机四种输入模式 MCU输入模式有浮空、上拉、下拉、模拟输入这四种模式,如果采用上拉或者下拉模式
    发表于 08-24 16:19

    变频器主要支持四种模式

    变频器主要支持四种模式:无PG的V/F模式,有PG的V/F模式,无PG的矢量控制模式,有PG的矢量模式
    发表于 09-03 06:57

    二维码的四种主要应用模式

    本文介绍二维码主要的四种应用模式,包括读取数据模式、解码上网模式、解码验证模式、解码通信模式
    发表于 01-25 11:52 3413次阅读

    WIFI模块四种工作模式介绍_WIFI模块工作模式浅析

    WIFI模块常见的四种工作模式:透传模式、串口指令模式、HTTPD Client模式、GPIO模式
    发表于 01-19 14:45 2.8w次阅读

    详解docker四种网络模式

    使用none模式Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何
    的头像 发表于 01-21 09:21 6594次阅读

    docker的4网络模式

    Docker 使用 Linux 桥接,在宿主机虚拟一个 Docker 容器网桥(docker0),Docker 启动一个
    的头像 发表于 08-14 11:50 1801次阅读

    docker的4网络模式配置

    Docker 使用 Linux 桥接,在宿主机虚拟一个 Docker 容器网桥(docker0),Docker 启动一个
    的头像 发表于 10-10 10:37 1390次阅读

    Docker容器网络的数据链路是什么

    单主机容器网络可能存在多个docker,分属于不同的bridge,它们之间有通信的需求。
    的头像 发表于 02-15 09:56 879次阅读
    <b class='flag-5'>Docker</b><b class='flag-5'>容器</b><b class='flag-5'>网络</b>的数据链路是什么

    测试电容器四种方法有哪些

    测试电容器四种方法 电容器是一非常常见的电子元件,它具有存储电能的能力。测试电容器的方法也非常多,下面我们将详细介绍
    的头像 发表于 09-01 15:11 1.4w次阅读

    docker容器容器之间通信

    Docker容器之间的通信方式、通信过程以及常见的通信模式。 一、Docker容器之间的通信方式 在Do
    的头像 发表于 11-23 09:36 1502次阅读

    docker进入容器的方法有哪些

    Docker是一流行的容器化平台,它能够快速构建、交付和运行应用程序。在使用Docker时,我们经常需要进入容器进行调试、管理和运行命令等
    的头像 发表于 11-23 09:45 1.1w次阅读

    介绍MCUboot支持的四种升级模式(2)

    介绍MCUboot支持的四种升级模式,分别是Overwrite、Swap、Direct XIP和加载到RAM中执行。由于FSP不支持第四种——加载到RAM中执行,因为我们重点介绍前三
    的头像 发表于 06-13 10:56 809次阅读
    介绍MCUboot支持的<b class='flag-5'>四种</b>升级<b class='flag-5'>模式</b>(2)