docker默認提供3種網絡模式:bridge橋接模式、host主機模式、none無網絡模式html
能夠經過命令 docker network ls 查看node
橋接模式是docker默認的網絡模式。當docker服務啓動後,會建立一個名字叫docker0的虛擬網橋,而後選一個與宿主機不同的網絡ip地址以及子網分配給docker0mysql
另外每建立一個容器就會新增一個容器網卡,而後以橋接方式架到docker0網橋中,docker0會以NAT地址轉換的方式經過宿主機的網卡,從而與公網進行通訊。linux
以下圖所示:sql
下面進行測試演示:docker
一、啓動docker服務後,經過命令 ip addr 發現docker0網卡ip爲172.17.0.1數據庫
二、啓動一個docker容器 docker run -itd centos:7 /bin/bash ,再進行一次 ip addr json
發現新增一個網卡veth506a249@if6centos
三、執行命令 yum install -y bridge-utils 安裝工具,使用命令 brctl show 查看一下橋接狀況tomcat
能夠看到容器的網卡橋接到docker0上
主機模式是指docker容器與公網通訊時使用的是宿主機的ip與端口,同時容器本身不會有ip地址,因此在這模式下容器與宿主機之間並無隔離很分明。
在容器啓動命令時用參數--net=host指定當前容器網絡模式 docker run -itd --net=host centos:7 /bin/bash
無網絡模式下至關於容器處於斷網狀態下,一樣沒有本身的ip地址。
建立容器時經過參數 --net=none 設置,這比較少使用。
上面講了關於docker的網絡模式,主要關於以哪一種方式讓服務器內部的容器與公網進行通訊。
一、假如使用的是默認的橋接網絡模式,啓動容器的時候須要使用參數--p 宿主機端口:容器端口設置端口的映射。
二、假如使用的是host主機模式,由於使用的是宿主機的ip與端口,那就直接能夠與公網通訊。
在實際的項目環境中,確定會存在多個服務間通訊的狀況。也就是多個容器之間通訊。
下面瞭解的是關於一個宿主機下多個服務間通訊的狀況。
舉個例子,例如多個服務訪問一個mysql數據庫。一般只須要在多個服務之間配置數據庫的地址就能夠了。
由於它們都是經過默認的bridge進行通訊的。
如今啓動兩個服務centos01和centos02
[root@localhost ~]# docker run -itd --name=centos01 mycentos:nettools /bin/bash 982a3d4cdb131bf33d217218c04aad278ac762376337e4180fd2eadc63599541 [root@localhost ~]# docker run -itd --name=centos02 mycentos:nettools /bin/bash e1c43e2000915b8256b1f0b6793b6f4bd1b2ff33ae1f32c6872ce21d4c5c8e4e
查看一下centos02的ip地址 docker inspect e1c43e2000915 ,發現是172.17.0.3
[ { "Id": "e1c43e2000915b8256b1f0b6793b6f4bd1b2ff33ae1f32c6872ce21d4c5c8e4e", "Created": "2020-02-18T08:17:13.893194133Z", "Path": "/bin/bash", "Args": [], "State": { "Status": "running", "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "Dead": false, "Pid": 19853, "ExitCode": 0, "Error": "", "StartedAt": "2020-02-18T08:17:14.24517605Z", "FinishedAt": "0001-01-01T00:00:00Z" }, "Image": "sha256:b92ca30f601cb7b594210e041eed8753aabb72dc5c2a18905b6272f5176ffdc0", "ResolvConfPath": "/var/lib/docker/containers/e1c43e2000915b8256b1f0b6793b6f4bd1b2ff33ae1f32c6872ce21d4c5c8e4e/resolv.conf", "HostnamePath": "/var/lib/docker/containers/e1c43e2000915b8256b1f0b6793b6f4bd1b2ff33ae1f32c6872ce21d4c5c8e4e/hostname", "HostsPath": "/var/lib/docker/containers/e1c43e2000915b8256b1f0b6793b6f4bd1b2ff33ae1f32c6872ce21d4c5c8e4e/hosts", "LogPath": "/var/lib/docker/containers/e1c43e2000915b8256b1f0b6793b6f4bd1b2ff33ae1f32c6872ce21d4c5c8e4e/e1c43e2000915b8256b1f0b6793b6f4bd1b2ff33ae1f32c6872ce21d4c5c8e4e-json.log", "Name": "/centos02", "RestartCount": 0, "Driver": "overlay2", "Platform": "linux", "MountLabel": "", "ProcessLabel": "", "AppArmorProfile": "", "ExecIDs": null, "HostConfig": { "Binds": null, "ContainerIDFile": "", "LogConfig": { "Type": "json-file", "Config": {} }, "NetworkMode": "default", "PortBindings": {}, "RestartPolicy": { "Name": "no", "MaximumRetryCount": 0 }, "AutoRemove": false, "VolumeDriver": "", "VolumesFrom": null, "CapAdd": null, "CapDrop": null, "Capabilities": null, "Dns": [], "DnsOptions": [], "DnsSearch": [], "ExtraHosts": null, "GroupAdd": null, "IpcMode": "private", "Cgroup": "", "Links": null, "OomScoreAdj": 0, "PidMode": "", "Privileged": false, "PublishAllPorts": false, "ReadonlyRootfs": false, "SecurityOpt": null, "UTSMode": "", "UsernsMode": "", "ShmSize": 67108864, "Runtime": "runc", "ConsoleSize": [ 0, 0 ], "Isolation": "", "CpuShares": 0, "Memory": 0, "NanoCpus": 0, "CgroupParent": "", "BlkioWeight": 0, "BlkioWeightDevice": [], "BlkioDeviceReadBps": null, "BlkioDeviceWriteBps": null, "BlkioDeviceReadIOps": null, "BlkioDeviceWriteIOps": null, "CpuPeriod": 0, "CpuQuota": 0, "CpuRealtimePeriod": 0, "CpuRealtimeRuntime": 0, "CpusetCpus": "", "CpusetMems": "", "Devices": [], "DeviceCgroupRules": null, "DeviceRequests": null, "KernelMemory": 0, "KernelMemoryTCP": 0, "MemoryReservation": 0, "MemorySwap": 0, "MemorySwappiness": null, "OomKillDisable": false, "PidsLimit": null, "Ulimits": null, "CpuCount": 0, "CpuPercent": 0, "IOMaximumIOps": 0, "IOMaximumBandwidth": 0, "MaskedPaths": [ "/proc/asound", "/proc/acpi", "/proc/kcore", "/proc/keys", "/proc/latency_stats", "/proc/timer_list", "/proc/timer_stats", "/proc/sched_debug", "/proc/scsi", "/sys/firmware" ], "ReadonlyPaths": [ "/proc/bus", "/proc/fs", "/proc/irq", "/proc/sys", "/proc/sysrq-trigger" ] }, "GraphDriver": { "Data": { "LowerDir": "/var/lib/docker/overlay2/fe38b48216b0e036c8a594635f6392d0f06f5da202e695a7052aa36ca510ddc1-init/diff:/var/lib/docker/overlay2/0dd6db3d6d6ee7fc48b4e13654a8d4414b545834df6e1524475649f2d67454de/diff:/var/lib/docker/overlay2/c9ac4844a5f33fad6a906ae9b4b86fa9f058c7ed1048bffad5b7a4aca454b33b/diff", "MergedDir": "/var/lib/docker/overlay2/fe38b48216b0e036c8a594635f6392d0f06f5da202e695a7052aa36ca510ddc1/merged", "UpperDir": "/var/lib/docker/overlay2/fe38b48216b0e036c8a594635f6392d0f06f5da202e695a7052aa36ca510ddc1/diff", "WorkDir": "/var/lib/docker/overlay2/fe38b48216b0e036c8a594635f6392d0f06f5da202e695a7052aa36ca510ddc1/work" }, "Name": "overlay2" }, "Mounts": [], "Config": { "Hostname": "e1c43e200091", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "Tty": true, "OpenStdin": true, "StdinOnce": false, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "Cmd": [ "/bin/bash" ], "Image": "mycentos:nettools", "Volumes": null, "WorkingDir": "", "Entrypoint": null, "OnBuild": null, "Labels": { "org.label-schema.build-date": "20191001", "org.label-schema.license": "GPLv2", "org.label-schema.name": "CentOS Base Image", "org.label-schema.schema-version": "1.0", "org.label-schema.vendor": "CentOS" } }, "NetworkSettings": { "Bridge": "", "SandboxID": "e8d1342d5dab4b15608ef4be8cacc83c30ca579c8ce676c39a91683da5e662b5", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": {}, "SandboxKey": "/var/run/docker/netns/e8d1342d5dab", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "f335c5cfcf7110d793f546ac44cf18bfd079f990ad3820646149f2adc28be692", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.3", "IPPrefixLen": 16, "IPv6Gateway": "", "MacAddress": "02:42:ac:11:00:03", "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "76342053278e2345a41515f3c5728095c5a97f6230f7a3edf5e41017c67a0a9f", "EndpointID": "f335c5cfcf7110d793f546ac44cf18bfd079f990ad3820646149f2adc28be692", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.3", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:03", "DriverOpts": null } } } } ]
接下來進入centos01而後嘗試ping一下172.17.0.3,發現是ping成功的
[root@localhost ~]# docker exec -it centos01 /bin/bash [root@982a3d4cdb13 /]# ping 172.17.0.3 PING 172.17.0.3 (172.17.0.3) 56(84) bytes of data. 64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.154 ms 64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.105 ms 64 bytes from 172.17.0.3: icmp_seq=3 ttl=64 time=0.121 ms 64 bytes from 172.17.0.3: icmp_seq=4 ttl=64 time=0.071 ms 64 bytes from 172.17.0.3: icmp_seq=5 ttl=64 time=0.070 ms ^C --- 172.17.0.3 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 3999ms rtt min/avg/max/mdev = 0.070/0.104/0.154/0.032 ms [root@982a3d4cdb13 /]#
而後嘗試ping一下centos02,發現是ping失敗的
[root@982a3d4cdb13 /]# ping centos02 ping: centos02: Name or service not known
也就是說目前在默認bridge下是無法經過容器名稱來進行通訊的
回到宿主機查看一下bridge的信息,發現配置容器的相關網絡信息。
[root@localhost ~]# docker network inspect bridge [ { "Name": "bridge", "Id": "76342053278e2345a41515f3c5728095c5a97f6230f7a3edf5e41017c67a0a9f", "Created": "2020-02-17T07:17:21.082636014+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "982a3d4cdb131bf33d217218c04aad278ac762376337e4180fd2eadc63599541": { "Name": "centos01", "EndpointID": "6d05788dc1e1ae12d6048879d5a0dc5012db828258e2de3ca91a7a1e1bc7cc33", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" }, "e1c43e2000915b8256b1f0b6793b6f4bd1b2ff33ae1f32c6872ce21d4c5c8e4e": { "Name": "centos02", "EndpointID": "f335c5cfcf7110d793f546ac44cf18bfd079f990ad3820646149f2adc28be692", "MacAddress": "02:42:ac:11:00:03", "IPv4Address": "172.17.0.3/16", "IPv6Address": "" } }, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ]
在docker中容器間直接經過ip進行服務訪問是存在弊端的。假如上面例子中mysql的忽然掛掉重啓也失敗,只能從新run一個。這時ip可能會發生變化,那就須要進去直接跟mysql通訊的服務修改相關配置信息,就很不友好。
所以Docker也提供了基於容器名來與其它容器通訊。
所謂單向通訊是指只能單方面發起網絡請求。例如一個功能服務請求mysql服務器,一般mysql服務器不須要訪問功能服務。
一樣啓動兩個服務進行模擬操做。一個模擬mysql,一個模擬tomcat。tomcat服務經過 --link mysql link到mysql服務中
記住,mysql服務要首先啓動,否則會報錯!
[root@localhost ~]# docker run -itd --name mysql mycentos:nettools /bin/bash 97ad026117718a0524eec1eb7db04a0dc3317b228b44abcc2b65a857919d8589 [root@localhost ~]# docker run -itd --name tomcat --link mysql mycentos:nettools /bin/bash 14c127543930d9c992f38514ba1b3db30a9e350272f41800e3e6870be5357450
接着進入tomcat容器中,經過容器名mysql使用ping命令
[root@localhost ~]# docker exec -it 14c12754393 /bin/bash [root@14c127543930 /]# ping mysql PING mysql (172.17.0.2) 56(84) bytes of data. 64 bytes from mysql (172.17.0.2): icmp_seq=1 ttl=64 time=0.109 ms 64 bytes from mysql (172.17.0.2): icmp_seq=2 ttl=64 time=0.118 ms 64 bytes from mysql (172.17.0.2): icmp_seq=3 ttl=64 time=0.140 ms ^C --- mysql ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2000ms rtt min/avg/max/mdev = 0.109/0.122/0.140/0.015 ms
在網絡中經過ping域名解析,無非就是經過本地hosts文件配置路由規則進行解析,還有就是經過DNS服務器解析
查看一下該hosts文件,發現配置了mysql容器的ip地址信息
[root@14c127543930 /]# cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.2 mysql 97ad02611771 172.17.0.3 14c127543930
接下來進入mysql容器嘗試ping一下tomcat容器,發現ping失敗
[root@localhost ~]# docker exec -it 97ad026117 /bin/bash [root@97ad02611771 /]# ping tomcat ping: tomcat: Name or service not known
也就是說經過--link實現單向通訊,路由規則是經過改寫hosts文件實現。
從 Docker1.10 之後,docker daemon 實現了一個內嵌的 docker dns server,使容器能夠直接經過「容器名」通訊。
不過不能使用默認bridge,須要自定義網橋
建立一個新的網橋def_bridge:
[root@localhost ~]# docker network create -d bridge def_bridge faeddc1fbfbf98f6572766003ff2cc27a023d43699fd994397013e09077c3784
啓動兩個容器名字分別爲mysql和tomcat
[root@localhost ~]# docker run -itd --name mysql mycentos:nettools /bin/bash 6a9f1e9d0bb051ea31e5727193a1aed99b8039c2cde629fe2bd387def1abb5bd [root@localhost ~]# docker run -itd --name tomcat mycentos:nettools /bin/bash 3e5950876d69712c3e2f8fd10268c9a21f1f21dd9937d1010ad2d5f709932831
而後將兩個啓動的容器都加入新增的網橋
[root@localhost ~]# docker network connect def_bridge mysql [root@localhost ~]# docker network connect def_bridge tomcat
能夠進入網橋查看一下,發現加入成功
[root@localhost ~]# docker network inspect def_bridge [ { "Name": "def_bridge", "Id": "faeddc1fbfbf98f6572766003ff2cc27a023d43699fd994397013e09077c3784", "Created": "2020-02-18T17:52:43.297517269+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "3e5950876d69712c3e2f8fd10268c9a21f1f21dd9937d1010ad2d5f709932831": { "Name": "tomcat", "EndpointID": "581356d1b23d64a76f0d83d1ee3416deea97e0c5d577070ac3f4d1bf94ee1dd9", "MacAddress": "02:42:ac:12:00:03", "IPv4Address": "172.18.0.3/16", "IPv6Address": "" }, "6a9f1e9d0bb051ea31e5727193a1aed99b8039c2cde629fe2bd387def1abb5bd": { "Name": "mysql", "EndpointID": "6d06e5719fa26e2b0f2007a1cc2e25282faaa39d0347b02fdb63c823e49b20e5", "MacAddress": "02:42:ac:12:00:02", "IPv4Address": "172.18.0.2/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ]
分別進入兩個容器經過容器名互ping,發現ping成功
[root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3e5950876d69 mycentos:nettools "/bin/bash" 6 minutes ago Up 6 minutes tomcat 6a9f1e9d0bb0 mycentos:nettools "/bin/bash" 6 minutes ago Up 6 minutes mysql [root@localhost ~]# docker exec -it 6a9f1e9d0bb0 /bin/bash [root@6a9f1e9d0bb0 /]# ping tomcat PING tomcat (172.18.0.3) 56(84) bytes of data. 64 bytes from tomcat.def_bridge (172.18.0.3): icmp_seq=1 ttl=64 time=0.100 ms 64 bytes from tomcat.def_bridge (172.18.0.3): icmp_seq=2 ttl=64 time=0.057 ms 64 bytes from tomcat.def_bridge (172.18.0.3): icmp_seq=3 ttl=64 time=0.097 ms 64 bytes from tomcat.def_bridge (172.18.0.3): icmp_seq=4 ttl=64 time=0.060 ms --- tomcat ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3002ms rtt min/avg/max/mdev = 0.057/0.078/0.100/0.021 ms [root@6a9f1e9d0bb0 /]# exit exit [root@localhost ~]# docker exec -it 3e5950876d69 /bin/bash [root@3e5950876d69 /]# ping mysql PING mysql (172.18.0.2) 56(84) bytes of data. 64 bytes from mysql.def_bridge (172.18.0.2): icmp_seq=1 ttl=64 time=0.040 ms 64 bytes from mysql.def_bridge (172.18.0.2): icmp_seq=2 ttl=64 time=0.067 ms 64 bytes from mysql.def_bridge (172.18.0.2): icmp_seq=3 ttl=64 time=0.055 ms 64 bytes from mysql.def_bridge (172.18.0.2): icmp_seq=4 ttl=64 time=0.130 ms --- mysql ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3000ms rtt min/avg/max/mdev = 0.040/0.073/0.130/0.034 ms
而後檢查一下tomcat容器的hosts文件以及resolv.conf文件
發現hosts文件沒有配置路由規則,而resolv.conf中配置了dns server 127.0.0.11
[root@3e5950876d69 /]# cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.3 3e5950876d69 172.18.0.3 3e5950876d69 [root@3e5950876d69 /]# cat /etc/resolv.conf nameserver 127.0.0.11 options ndots:0
也就是說經過自定義bridge雙向通訊是經過內置的dns服務實現IP地址的解析工做
本文做者:hjjay
原文出處:https://www.cnblogs.com/jayhou/p/12319655.html 本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文連接。