面试官Docker有几种网络模式?5年工作经验都表示答不上来
docker容器网络
Docker在安装后自动提供3种网络,可以使用dockernetworkls命令查看〔rootlocalhost〕dockernetworklsNETWORKIDNAMEDRIVERSCOPEcd97bb997b84bridgebridgelocal0a04824fc9b6hosthostlocal4dcb8fbdb599nonenulllocal
Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为ContainerIP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的ContainerIP直接通信。docker的4种网络模式
网络模式
配置
说明
host
networkhost
容器和宿主机共享Networknamespace
container
networkcontainer:NAMEORID
容器和另外一个容器共享Networknamespace
none
networknone
容器有独立的Networknamespace,但并没有对其进行任何网络设置,如分配vethpair和网桥连接,配置IP等
bridge
network
bridge默认模式
bridge模式
当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡vethpair设备,Docker将vethpair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctlshow命令查看。
bridge模式是docker的默认网络模式,不写network参数,就是bridge模式。使用dockerrunp时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptablestnatvnL查看。
bridge模式如下图所示:
假设上图的docker2中运行了一个nginx,大家来想几个问题:同主机间两个容器间是否可以直接通信?比如在docker1上能不能直接访问到docker2的nginx站点?在宿主机上能否直接访问到docker2的nginx站点?在另一台主机上如何访问node1上的这个nginx站点呢?DNAT发布?
Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法通过直接ContainerIP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射),即dockerrun创建容器时候通过p或P参数来启用,访问容器的时候就通过〔宿主机IP〕:〔容器端口〕访问容器。container模式
这个模式指定新创建的容器和已经存在的一个容器共享一个NetworkNamespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP,而是和一个指定的容器共享IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。
container模式如下图所示:
host模式
如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的NetworkNamespace,而是和宿主机共用一个NetworkNamespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是dockerhost上已经使用的端口就不能再用了,网络的隔离性不好。
Host模式如下图所示:
none模式
使用none模式,Docker容器拥有自己的NetworkNamespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过networknone来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
应用场景:启动一个容器处理数据,比如转换数据格式一些后台的计算和处理任务
none模式如下图所示:
dockernetworkinspectbridge查看bridge网络的详细配置docker容器网络配置Linux内核实现名称空间的创建ipnetns命令
可以借助ipnetns命令来完成对NetworkNamespace的各种操作。ipnetns命令来自于iproute安装包,一般系统会默认安装,如果没有的话,请自行安装。
注意:ipnetns命令修改网络配置时需要sudo权限。
可以通过ipnetns命令完成对NetworkNamespace的相关操作,可以通过ipnetnshelp查看命令帮助信息:〔rootlocalhost〕ipnetnshelpUsage:ipnetnslistipnetnsaddNAMEipnetnssetNAMENETNSIDip〔all〕netnsdelete〔NAME〕ipnetnsidentify〔PID〕ipnetnspidsNAMEip〔all〕netnsexec〔NAME〕cmd。。。ipnetnsmonitoripnetnslistid
默认情况下,Linux系统中是没有任何NetworkNamespace的,所以ipnetnslist命令不会返回任何信息。创建NetworkNamespace
通过命令创建一个名为ns0的命名空间:〔rootlocalhost〕ipnetnslist〔rootlocalhost〕ipnetnsaddns0〔rootlocalhost〕ipnetnslistns0
新创建的NetworkNamespace会出现在varrunnetns目录下。如果相同名字的namespace已经存在,命令会报Cannotcreatenamespacefilevarrunnetnsns0:Fileexists的错误。〔rootlocalhost〕lsvarrunnetnsns0〔rootlocalhost〕ipnetnsaddns0Cannotcreatenamespacefilevarrunnetnsns0:Fileexists
对于每个NetworkNamespace来说,它会有自己独立的网卡、路由表、ARP表、iptables等和网络相关的资源。操作NetworkNamespace
ip命令提供了ipnetnsexec子命令可以在对应的NetworkNamespace中执行命令。
查看新创建NetworkNamespace的网卡信息〔rootlocalhost〕ipnetnsexecns0ipaddr1:lo:LOOPBACKmtu65536qdiscnoopstateDOWNgroupdefaultqlen1000linkloopback00:00:00:00:00:00brd00:00:00:00:00:00
可以看到,新创建的NetworkNamespace中会默认创建一个lo回环网卡,此时网卡处于关闭状态。此时,尝试去ping该lo回环网卡,会提示Networkisunreachable〔rootlocalhost〕ipnetnsexecns0ping127。0。0。1connect:Networkisunreachable127。0。0。1是默认回环网卡
通过下面的命令启用lo回环网卡:〔rootlocalhost〕ipnetnsexecns0iplinksetloup〔rootlocalhost〕ipnetnsexecns0ping127。0。0。1PING127。0。0。1(127。0。0。1)56(84)bytesofdata。64bytesfrom127。0。0。1:icmpseq1ttl64time0。029ms64bytesfrom127。0。0。1:icmpseq2ttl64time0。029msC127。0。0。1pingstatistics2packetstransmitted,2received,0packetloss,time1036msrttminavgmaxmdev0。0290。0290。0290。000ms转移设备
我们可以在不同的NetworkNamespace之间转移设备(如veth)。由于一个设备只能属于一个NetworkNamespace,所以转移后在这个NetworkNamespace内就看不到这个设备了。
其中,veth设备属于可转移设备,而很多其它设备(如lo、vxlan、ppp、bridge等)是不可以转移的。vethpair
vethpair全称是VirtualEthernetPair,是一个成对的端口,所有从这对端口一端进入的数据包都将从另一端出来,反之也是一样。
引入vethpair是为了在不同的NetworkNamespace直接进行通信,利用它可以直接将两个NetworkNamespace连接起来。
创建vethpair〔rootlocalhost〕iplinkaddtypeveth〔rootlocalhost〕ipa4:veth0veth1:BROADCAST,MULTICAST,MDOWNmtu1500qdiscnoopstateDOWNgroupdefaultqlen1000linkether0a:f4:e2:2d:37:fbbrdff:ff:ff:ff:ff:ff5:veth1veth0:BROADCAST,MULTICAST,MDOWNmtu1500qdiscnoopstateDOWNgroupdefaultqlen1000linkether5e:7e:f6:59:f0:4fbrdff:ff:ff:ff:ff:ff
可以看到,此时系统中新增了一对vethpair,将veth0和veth1两个虚拟网卡连接了起来,此时这对vethpair处于未启用状态。实现NetworkNamespace间通信
下面我们利用vethpair实现两个不同的NetworkNamespace之间的通信。刚才我们已经创建了一个名为ns0的NetworkNamespace,下面再创建一个信息NetworkNamespace,命名为ns1〔rootlocalhost〕ipnetnsaddns1〔rootlocalhost〕ipnetnslistns1ns0
然后我们将veth0加入到ns0,将veth1加入到ns1〔rootlocalhost〕iplinksetveth0netnsns0〔rootlocalhost〕iplinksetveth1netnsns1
然后我们分别为这对vethpair配置上ip地址,并启用它们〔rootlocalhost〕ipnetnsexecns0iplinksetveth0up〔rootlocalhost〕ipnetnsexecns0ipaddradd192。0。0。124devveth0〔rootlocalhost〕ipnetnsexecns1iplinksetveth1up〔rootlocalhost〕ipnetnsexecns1ipaddradd192。0。0。224devveth1
查看这对vethpair的状态〔rootlocalhost〕ipnetnsexecns0ipa1:lo:LOOPBACK,UP,LOWERUPmtu65536qdiscnoqueuestateUNKNOWNgroupdefaultqlen1000linkloopback00:00:00:00:00:00brd00:00:00:00:00:00inet127。0。0。18scopehostlovalidlftforeverpreferredlftforeverinet6::1128scopehostvalidlftforeverpreferredlftforever4:veth0if5:BROADCAST,MULTICAST,UP,LOWERUPmtu1500qdiscnoqueuestateUPgroupdefaultqlen1000linkether0a:f4:e2:2d:37:fbbrdff:ff:ff:ff:ff:fflinknetnsns1inet192。0。0。124scopeglobalveth0validlftforeverpreferredlftforeverinet6fe80::8f4:e2ff:fe2d:37fb64scopelinkvalidlftforeverpreferredlftforever〔rootlocalhost〕ipnetnsexecns1ipa1:lo:LOOPBACKmtu65536qdiscnoopstateDOWNgroupdefaultqlen1000linkloopback00:00:00:00:00:00brd00:00:00:00:00:005:veth1if4:BROADCAST,MULTICAST,UP,LOWERUPmtu1500qdiscnoqueuestateUPgroupdefaultqlen1000linkether5e:7e:f6:59:f0:4fbrdff:ff:ff:ff:ff:fflinknetnsns0inet192。0。0。224scopeglobalveth1validlftforeverpreferredlftforeverinet6fe80::5c7e:f6ff:fe59:f04f64scopelinkvalidlftforeverpreferredlftforever
从上面可以看出,我们已经成功启用了这个vethpair,并为每个veth设备分配了对应的ip地址。我们尝试在ns1中访问ns0中的ip地址〔rootlocalhost〕ipnetnsexecns1ping192。0。0。1PING192。0。0。1(192。0。0。1)56(84)bytesofdata。64bytesfrom192。0。0。1:icmpseq1ttl64time0。033ms64bytesfrom192。0。0。1:icmpseq2ttl64time0。041msC192。0。0。1pingstatistics2packetstransmitted,2received,0packetloss,time1001msrttminavgmaxmdev0。0330。0370。0410。004ms〔rootlocalhost〕ipnetnsexecns0ping192。0。0。2PING192。0。0。2(192。0。0。2)56(84)bytesofdata。64bytesfrom192。0。0。2:icmpseq1ttl64time0。025ms64bytesfrom192。0。0。2:icmpseq2ttl64time0。025msC192。0。0。2pingstatistics2packetstransmitted,2received,0packetloss,time1038msrttminavgmaxmdev0。0250。0250。0250。000ms
可以看到,vethpair成功实现了两个不同NetworkNamespace之间的网络交互。四种网络模式配置bridge模式配置〔rootlocalhost〕dockerrunitnametirmbusyboxifconfigeth0Linkencap:EthernetHWaddr02:42:AC:11:00:02inetaddr:172。17。0。2Bcast:172。17。255。255Mask:255。255。0。0UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1RXpackets:12errors:0dropped:0overruns:0frame:0TXpackets:0errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:0RXbytes:1032(1。0KiB)TXbytes:0(0。0B)loLinkencap:LocalLoopbackinetaddr:127。0。0。1Mask:255。0。0。0UPLOOPBACKRUNNINGMTU:65536Metric:1RXpackets:0errors:0dropped:0overruns:0frame:0TXpackets:0errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:1000RXbytes:0(0。0B)TXbytes:0(0。0B)
在创建容器时添加networkbridge与不加network选项效果是一致的〔rootlocalhost〕dockerrunitnamet1networkbridgermbusyboxifconfigeth0Linkencap:EthernetHWaddr02:42:AC:11:00:02inetaddr:172。17。0。2Bcast:172。17。255。255Mask:255。255。0。0UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1RXpackets:8errors:0dropped:0overruns:0frame:0TXpackets:0errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:0RXbytes:696(696。0B)TXbytes:0(0。0B)loLinkencap:LocalLoopbackinetaddr:127。0。0。1Mask:255。0。0。0UPLOOPBACKRUNNINGMTU:65536Metric:1RXpackets:0errors:0dropped:0overruns:0frame:0TXpackets:0errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:1000RXbytes:0(0。0B)TXbytes:0(0。0B)none模式配置〔rootlocalhost〕dockerrunitnamet1networknonermbusyboxifconfigaloLinkencap:LocalLoopbackinetaddr:127。0。0。1Mask:255。0。0。0UPLOOPBACKRUNNINGMTU:65536Metric:1RXpackets:0errors:0dropped:0overruns:0frame:0TXpackets:0errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:1000RXbytes:0(0。0B)TXbytes:0(0。0B)container模式配置
启动第一个容器〔rootlocalhost〕dockerrunditnameb3busyboxaf5ba32f990ebf5a46d7ecaf1eec67f1712bbef6ad7df37d52b7a8a498a592a0〔rootlocalhost〕dockerexecitb3binshifconfigeth0Linkencap:EthernetHWaddr02:42:AC:11:00:02inetaddr:172。17。0。2Bcast:172。17。255。255Mask:255。255。0。0UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1RXpackets:11errors:0dropped:0overruns:0frame:0TXpackets:0errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:0RXbytes:906(906。0B)TXbytes:0(0。0B)
启动第二个容器〔rootlocalhost〕dockerrunitnameb2rmbusyboxifconfigeth0Linkencap:EthernetHWaddr02:42:AC:11:00:03inetaddr:172。17。0。3Bcast:172。17。255。255Mask:255。255。0。0UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1RXpackets:6errors:0dropped:0overruns:0frame:0TXpackets:0errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:0RXbytes:516(516。0B)TXbytes:0(0。0B)
可以看到名为b2的容器IP地址是10。0。0。3,与第一个容器的IP地址不是一样的,也就是说并没有共享网络,此时如果我们将第二个容器的启动方式改变一下,就可以使名为b2的容器IP与B3容器IP一致,也即共享IP,但不共享文件系统。〔rootlocalhost〕dockerrunitnameb2rmnetworkcontainer:b3busyboxifconfigeth0Linkencap:EthernetHWaddr02:42:AC:11:00:02inetaddr:172。17。0。2Bcast:172。17。255。255Mask:255。255。0。0UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1RXpackets:14errors:0dropped:0overruns:0frame:0TXpackets:0errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:0RXbytes:1116(1。0KiB)TXbytes:0(0。0B)此时我们在b1容器上创建一个目录mkdirtmpdatalstmpdata
到b2容器上检查tmp目录会发现并没有这个目录,因为文件系统是处于隔离状态,仅仅是共享了网络而已。
在b2容器上部署一个站点echohelloworldtmpindex。htmllstmpindex。htmlhttpdhtmpnetstatantlActiveInternetconnections(serversandestablished)ProtoRecvQSendQLocalAddressForeignAddressStatetcp00:::80:::LISTEN
在b1容器上用本地地址去访问此站点wgetOq172。17。0。2:80helloworldhost模式配置
启动容器时直接指明模式为host〔rootlocalhost〕dockerrunitnameb2rmnetworkhostbusyboxifconfigdocker0Linkencap:EthernetHWaddr02:42:B8:7F:8E:2Cinetaddr:172。17。0。1Bcast:172。17。255。255Mask:255。255。0。0inet6addr:fe80::42:b8ff:fe7f:8e2c64Scope:LinkUPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1RXpackets:3errors:0dropped:0overruns:0frame:0TXpackets:20errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:0RXbytes:116(116。0B)TXbytes:1664(1。6KiB)ens33Linkencap:EthernetHWaddr00:0C:29:95:19:47inetaddr:192。168。203。138Bcast:192。168。203。255Mask:255。255。255。0inet6addr:fe80::2e61:1ea3:c05a:3d9b64Scope:LinkUPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1RXpackets:9626errors:0dropped:0overruns:0frame:0TXpackets:3950errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:1000RXbytes:3779562(3。6MiB)TXbytes:362386(353。8KiB)loLinkencap:LocalLoopbackinetaddr:127。0。0。1Mask:255。0。0。0inet6addr:::1128Scope:HostUPLOOPBACKRUNNINGMTU:65536Metric:1RXpackets:0errors:0dropped:0overruns:0frame:0TXpackets:0errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:1000RXbytes:0(0。0B)TXbytes:0(0。0B)veth09ee47eLinkencap:EthernetHWaddrB2:10:53:7B:66:AEinet6addr:fe80::b010:53ff:fe7b:66ae64Scope:LinkUPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1RXpackets:3errors:0dropped:0overruns:0frame:0TXpackets:19errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:0RXbytes:158(158。0B)TXbytes:1394(1。3KiB)
此时如果我们在这个容器中启动一个http站点,我们就可以直接用宿主机的IP直接在浏览器中访问这个容器中的站点了。容器的常用操作查看容器的主机名〔rootlocalhost〕dockerrunitnamet1networkbridgermbusyboxhostname48cb45a0b2e7在容器启动时注入主机名〔rootlocalhost〕dockerrunitnamet1networkbridgehostnameljlrmbusyboxhostnameljlcatetchosts127。0。0。1localhost::1localhostip6localhostip6loopbackfe00::0ip6localnetff00::0ip6mcastprefixff02::1ip6allnodesff02::2ip6allrouters172。17。0。3ljlcatetcresolv。confGeneratedbyNetworkManagersearchlocaldomainnameserver192。168。203。2pingwww。baidu。comPINGwww。baidu。com(182。61。200。7):56databytes64bytesfrom182。61。200。7:seq0ttl127time31。929ms64bytesfrom182。61。200。7:seq1ttl127time41。062ms64bytesfrom182。61。200。7:seq2ttl127time31。540msCwww。baidu。compingstatistics3packetstransmitted,3packetsreceived,0packetlossroundtripminavgmax31。54034。84341。062ms手动指定容器要使用的DNS〔rootlocalhost〕dockerrunitnamet1networkbridgehostnameljldns114。114。114。114rmbusyboxcatetcresolv。confsearchlocaldomainnameserver114。114。114。114nslookuptypeawww。baidu。comServer:114。114。114。114Address:114。114。114。114:53Nonauthoritativeanswer:www。baidu。comcanonicalnamewww。a。shifen。comName:www。a。shifen。comAddress:182。61。200。6Name:www。a。shifen。comAddress:182。61。200。7手动往etchosts文件中注入主机名到IP地址的映射〔rootlocalhost〕dockerrunitnamet1networkbridgehostnameljladdhostwww。a。com:1。1。1。1rmbusyboxcatetchosts127。0。0。1localhost::1localhostip6localhostip6loopbackfe00::0ip6localnetff00::0ip6mcastprefixff02::1ip6allnodesff02::2ip6allrouters1。1。1。1www。a。com172。17。0。3ljl开放容器端口
执行dockerrun的时候有个p选项,可以将容器中的应用端口映射到宿主机中,从而实现让外部主机可以通过访问宿主机的某端口来访问容器内应用的目的。
p选项能够使用多次,其所能够暴露的端口必须是容器确实在监听的端口。
p选项的使用格式:pcontainerPort将指定的容器端口映射至主机所有地址的一个动态端口phostPort:containerPort将容器端口containerPort映射至指定的主机端口hostPortpip::containerPort将指定的容器端口containerPort映射至主机指定ip的动态端口pip:hostPort:containerPort将指定的容器端口containerPort映射至主机指定ip的端口hostPort
动态端口指的是随机端口,具体的映射结果可使用dockerport命令查看。〔rootlocalhost〕dockerrunditnameweb1p192。168。203。138::80httpde97bc1774e40132659990090f0e98a308a7f83986610ca89037713e9af8a6b9f〔rootlocalhost〕dockerpsCONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMESe97bc1774e40httpdhttpdforeground6secondsagoUp5seconds192。168。203。138:4915380tcpweb1af5ba32f990ebusyboxsh48minutesagoUp48minutesb3〔rootlocalhost〕ssantlStateRecvQSendQLocalAddress:PortPeerAddress:PortProcessLISTEN0128192。168。203。138:491530。0。0。0:LISTEN01280。0。0。0:220。0。0。0:LISTEN0128〔::〕:22〔::〕:
以上命令执行后会一直占用着前端,我们新开一个终端连接来看一下容器的80端口被映射到了宿主机的什么端口上〔rootlocalhost〕dockerportweb180tcp192。168。203。138:49153
由此可见,容器的80端口被暴露到了宿主机的49153端口上,此时我们在宿主机上访问一下这个端口看是否能访问到容器内的站点〔rootlocalhost〕curlhttp:192。168。203。138:49153htmlbodyh1Itworks!h1bodyhtml
iptables防火墙规则将随容器的创建自动生成,随容器的删除自动删除规则。〔rootlocalhost〕iptablestnatnvLChainPREROUTING(policyACCEPT0packets,0bytes)pktsbytestargetprotoptinoutsourcedestination3164DOCKERall0。0。0。000。0。0。00ADDRTYPEmatchdsttypeLOCALChainINPUT(policyACCEPT0packets,0bytes)pktsbytestargetprotoptinoutsourcedestinationChainPOSTROUTING(policyACCEPT0packets,0bytes)pktsbytestargetprotoptinoutsourcedestination4261MASQUERADEall!docker0172。17。0。0160。0。0。0000MASQUERADEtcp172。17。0。3172。17。0。3tcpdpt:80ChainOUTPUT(policyACCEPT0packets,0bytes)pktsbytestargetprotoptinoutsourcedestination2120DOCKERall0。0。0。00!127。0。0。08ADDRTYPEmatchdsttypeLOCALChainDOCKER(2references)pktsbytestargetprotoptinoutsourcedestination160RETURNalldocker00。0。0。000。0。0。00160DNATtcp!docker00。0。0。00192。168。203。138tcpdpt:49153to:172。17。0。3:80
将容器端口映射到指定IP的随机端口〔rootlocalhost〕dockerrunditnameweb1p192。168。203。138::80httpd
在另一个终端上查看端口映射情况〔rootlocalhost〕dockerportweb180tcp192。168。203。138:49153自定义docker0桥的网络属性信息
自定义docker0桥的网络属性信息需要修改etcdockerdaemon。json配置文件〔rootlocalhost〕cdetcdocker〔rootlocalhostdocker〕vimdaemon。json〔rootlocalhostdocker〕systemctldaemonreload〔rootlocalhostdocker〕systemctlrestartdocker{registrymirrors:〔https:4hygggbu。mirror。aliyuncs。com〕,bip:192。168。1。524}EOF〔rootlocalhost〕vimlibsystemdsystemdocker。serviceExecStartusrbindockerdHfd:containerdruncontainerdcontainerd。sockHtcp:0。0。0。0:2375Hunix:varrundocker。sock〔rootlocalhost〕systemctldaemonreload〔rootlocalhost〕systemctlrestartdocker
在客户端上向dockerd直接传递Hhost选项指定要控制哪台主机上的docker容器〔rootlocalhost〕dockerH192。168。203。138:2375psCONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMESe97bc1774e40httpdhttpdforeground30minutesagoUp11seconds192。168。203。138:4915380tcpweb1af5ba32f990ebusyboxshAboutanhouragoUp14secondsb3
创建新网络〔rootlocalhost〕dockernetworkcreateljldbridge883eda50812bb214c04986ca110dbbcb7600eba8b033f2084cd4d750b0436e12〔rootlocalhost〕dockernetworklsNETWORKIDNAMEDRIVERSCOPE0c5f4f114c27bridgebridgelocal8c2d14f1fb82hosthostlocal883eda50812bljlbridgelocal85ed12d38815nonenulllocal
创建一个额外的自定义桥,区别于docker0〔rootlocalhost〕dockernetworkcreatedbridgesubnet192。168。2。024gateway192。168。2。1br0af9ba80deb619de3167939ec5b6d6136a45dce90907695a5bc5ed4608d188b99〔rootlocalhost〕dockernetworklsNETWORKIDNAMEDRIVERSCOPEaf9ba80deb61br0bridgelocal0c5f4f114c27bridgebridgelocal8c2d14f1fb82hosthostlocal883eda50812bljlbridgelocal85ed12d38815nonenulllocal
使用新创建的自定义桥来创建容器:〔rootlocalhost〕dockerrunitnameb1networkbr0busyboxifconfigeth0Linkencap:EthernetHWaddr02:42:C0:A8:02:02inetaddr:192。168。2。2Bcast:192。168。2。255Mask:255。255。255。0UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1RXpackets:11errors:0dropped:0overruns:0frame:0TXpackets:0errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:0RXbytes:962(962。0B)TXbytes:0(0。0B)
再创建一个容器,使用默认的bridge桥:〔rootlocalhost〕dockerrunnameb2itbusyboxlsbindevetchomeprocrootsystmpusrvarifconfigeth0Linkencap:EthernetHWaddr02:42:C0:A8:01:03inetaddr:192。168。1。3Bcast:192。168。1。255Mask:255。255。255。0UPBROADCASTRUNNINGMULTICASTMTU:1500Metric:1RXpackets:6errors:0dropped:0overruns:0frame:0TXpackets:0errors:0dropped:0overruns:0carrier:0collisions:0txqueuelen:0RXbytes:516(516。0B)TXbytes:0(0。0B)