參考資料:B站狂神教程
https://www.bilibili.com/video/BV1og4y1q7M4?p=36
Docker的網絡模式
root@KitDevVps:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
1375b7ef4bbc bridge bridge local
b29eab4db971 host host local
acfcd6eaf888 none null local
有以下幾種網絡模式:
- bridge:橋接(docker默認)
- none:不配置網絡
- host:和宿主機共享網絡
- container:容器網絡連通(用的很少,不建議使用,局限性很大)
我們自己創建網絡,也是用bridge橋接模式。
創建網絡
自己創建網絡的命令是docker network create
。
我們每次run出容器的時候,默認使用bridge模式,run的命令中默認有--net bridge
這么一個選項。因為bridge是docker0的Name。我們自己創建網絡的時候就應該避開bridge這個名字。假如我們自己create的網絡叫bridge02,我們想讓自己的容器加入這個網絡的時候,run的時候就加上--net bridge02
就可以了。
我們看一下docker network create
這個命令怎么用:
root@KitDevVps:~# docker network create -h
Flag shorthand -h has been deprecated, please use --help
Usage: docker network create [OPTIONS] NETWORK
Create a network
Options:
--attachable Enable manual container attachment
--aux-address map Auxiliary IPv4 or IPv6 addresses used by Network driver (default map[])
--config-from string The network from which copying the configuration
--config-only Create a configuration only network
-d, --driver string Driver to manage the Network (default "bridge")
--gateway strings IPv4 or IPv6 Gateway for the master subnet
--ingress Create swarm routing-mesh network
--internal Restrict external access to the network
--ip-range strings Allocate container ip from a sub-range
--ipam-driver string IP Address Management Driver (default "default")
--ipam-opt map Set IPAM driver specific options (default map[])
--ipv6 Enable IPv6 networking
--label list Set metadata on a network
-o, --opt map Set driver specific options (default map[])
--scope string Control the network's scope
--subnet strings Subnet in CIDR format that represents a network segment
其中的subnet子網一定要配,加上掩碼;driver默認就是bridge模式,寫不寫都行;gateway也寫一下,就是網關,網絡從哪個地方出去。我們模仿路由器配一個:
root@KitDevVps:~# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
0df835de9886ed3cf76b071281ddc521c33502914aeb69a8e1bbc817dbcdff0a
其中網段192.168.0.0,掩碼位數16.也就是有255*255個ip可用。如果是24的話就只有255個ip可用,這一塊是計算機網絡的知識。網關是192.168.0.1。網絡取名為mynet。
用docker network ls
看一下我們的網絡有沒有:
root@KitDevVps:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
1375b7ef4bbc bridge bridge local
b29eab4db971 host host local
0df835de9886 mynet bridge local
acfcd6eaf888 none null local
已經有了,在倒數第二行。看一下網絡的詳細信息:
root@KitDevVps:~# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "0df835de9886ed3cf76b071281ddc521c33502914aeb69a8e1bbc817dbcdff0a",
"Created": "2020-07-05T09:39:03.14488529Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
可以看到子網和網關都是我們自己配置的,沒有問題。
我們啟動兩個centos容器,放在這個網絡里:
root@KitDevVps:~# docker run -d -it --name centos01 --net mynet centos
43f47db12bf4a8be9ea6172a89a44c530a23b29de49bf2a5ef95a88308675025
root@KitDevVps:~# docker run -d -it --name centos02 --net mynet centos
2a26067838f1724347ef50a1b8988a50603715e514fb288ab86401571dc70173
root@KitDevVps:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a26067838f1 centos "/bin/bash" 7 seconds ago Up 6 seconds centos02
43f47db12bf4 centos "/bin/bash" 16 seconds ago Up 15 seconds centos01
1cdd55fd90c5 nginx "/docker-entrypoint.…" 2 days ago Up 2 days 0.0.0.0:80->80/tcp nginx1
再看一下mynet的詳細信息:
root@KitDevVps:~# docker network inspect mynet
[
...
"Containers": {
"2a26067838f1724347ef50a1b8988a50603715e514fb288ab86401571dc70173": {
"Name": "centos02",
"EndpointID": "83e59d8f388561cb006564de55bb1c76278ab54b0e87f1f7e671a9962efe3608",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"43f47db12bf4a8be9ea6172a89a44c530a23b29de49bf2a5ef95a88308675025": {
"Name": "centos01",
"EndpointID": "b0a1f17acc6a4c835952ae4e764c7f7e26a90fc3ce28be97cf9bb8c2ee0c10a4",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
]
可以看到containers中有了我們的兩個容器,他們的ip地址也是這個網段的。
使用容器名代替ip地址來ping
自己創建網絡有什么好處呢,好處就是可以直接使用容器名來互ping:
root@KitDevVps:~# docker exec -it centos01 ping centos02
PING centos02 (192.168.0.3) 56(84) bytes of data.
64 bytes from centos02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.099 ms
64 bytes from centos02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.167 ms
64 bytes from centos02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.079 ms
64 bytes from centos02.mynet (192.168.0.3): icmp_seq=4 ttl=64 time=0.090 ms
^C
--- centos02 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 45ms
rtt min/avg/max/mdev = 0.079/0.108/0.167/0.036 ms
即現在不使用--link
也可以連接成功了。
我們自定義的網絡,docker幫我們維護好了對應的關系,docker0則沒有這個功能。
比如我有一個redis的集群,就可以打一個網絡。還有一個mssql的集群,也可以搭一個網絡。網絡之間是互相隔離的。不同集群使用不同網絡,集群都是健康的。
多個網絡之間的連通
docker0網絡中的一個容器如何訪問mynet網絡?顯然也要通過docker network
命令來找線索:
root@KitDevVps:~# docker network -h
Flag shorthand -h has been deprecated, please use --help
Usage: docker network COMMAND
Manage networks
Commands:
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 networks
Run 'docker network COMMAND --help' for more information on a command.
可以看到第一條命令connect,介紹是連接一個容器到一個網絡。看一下這個命令怎么用:
root@KitDevVps:~# docker network connect -h
Flag shorthand -h has been deprecated, please use --help
Usage: docker network connect [OPTIONS] NETWORK CONTAINER
Connect a container to a network
Options:
--alias strings Add network-scoped alias for the container
--driver-opt strings driver options for the network
--ip string IPv4 address (e.g., 172.30.100.104)
--ip6 string IPv6 address (e.g., 2001:db8::33)
--link list Add link to another container
--link-local-ip strings Add a link-local address for the container
root@KitDevVps:~#
顯然用法就是docket network connect [可選選項] 網絡 容器
。現在我們有centos01和02運行在mynet上,我們在docker0上run出個centos03:
root@KitDevVps:~# docker exec -it centos03 ping centos01
ping: centos01: Name or service not known
root@KitDevVps:~# docker exec -it centos03 ping 43f47db12bf4
ping: 43f47db12bf4: Name or service not known
可以看到無論ping名還是id都ping不通。試一下前面我們查到的命令:
root@KitDevVps:~# docker network connect mynet centos03
root@KitDevVps:~# docker exec -it centos03 ping centos01
PING centos01 (192.168.0.2) 56(84) bytes of data.
64 bytes from centos01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.163 ms
64 bytes from centos01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.081 ms
64 bytes from centos01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.104 ms
64 bytes from centos01.mynet (192.168.0.2): icmp_seq=4 ttl=64 time=0.107 ms
^C
--- centos01 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 46ms
rtt min/avg/max/mdev = 0.081/0.113/0.163/0.032 ms
運行docker network connect mynet centos03
后沒有返回東西,但centos03已經可以ping通centos01了,而且還是用容器名字直接ping通。
我們看一下mynet的詳細信息:
root@KitDevVps:~# docker network inspect mynet
[
...
"Containers": {
"2a26067838f1724347ef50a1b8988a50603715e514fb288ab86401571dc70173": {
"Name": "centos02",
"EndpointID": "83e59d8f388561cb006564de55bb1c76278ab54b0e87f1f7e671a9962efe3608",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"43f47db12bf4a8be9ea6172a89a44c530a23b29de49bf2a5ef95a88308675025": {
"Name": "centos01",
"EndpointID": "b0a1f17acc6a4c835952ae4e764c7f7e26a90fc3ce28be97cf9bb8c2ee0c10a4",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
"62bad532ae1925a4a33388f629931b573bcd1b6fd00e9ab5b99799dbdb17c73b": {
"Name": "centos03",
"EndpointID": "763c6c021ae7a05d3099d6c64c3dd28b1a574ecbf46e2689441e17afccc58da6",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
]
可以看到centos03直接被加入到了mynet這個網絡里。這樣centos03這個容器就擁有了兩個ip地址,它在docker0中有一個,在mynet中還有一個。
centos01能ping通centos03嗎?
root@KitDevVps:~# docker exec -it centos01 ping centos03
PING centos03 (192.168.0.4) 56(84) bytes of data.
64 bytes from centos03.mynet (192.168.0.4): icmp_seq=1 ttl=64 time=0.067 ms
64 bytes from centos03.mynet (192.168.0.4): icmp_seq=2 ttl=64 time=0.081 ms
64 bytes from centos03.mynet (192.168.0.4): icmp_seq=3 ttl=64 time=0.077 ms
64 bytes from centos03.mynet (192.168.0.4): icmp_seq=4 ttl=64 time=0.092 ms
^C
--- centos03 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 42ms
rtt min/avg/max/mdev = 0.067/0.079/0.092/0.010 ms
02能ping通03嗎?
root@KitDevVps:~# docker exec -it centos02 ping centos03
PING centos03 (192.168.0.4) 56(84) bytes of data.
64 bytes from centos03.mynet (192.168.0.4): icmp_seq=1 ttl=64 time=0.094 ms
64 bytes from centos03.mynet (192.168.0.4): icmp_seq=2 ttl=64 time=0.127 ms
64 bytes from centos03.mynet (192.168.0.4): icmp_seq=3 ttl=64 time=0.100 ms
64 bytes from centos03.mynet (192.168.0.4): icmp_seq=4 ttl=64 time=0.115 ms
^C
--- centos03 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 53ms
rtt min/avg/max/mdev = 0.094/0.109/0.127/0.012 ms
其實后面這兩次都是廢話,都在同一個網絡里了當然能ping通,而且ping的地址是03在mynet中的地址,不是在docker0中的地址。玩這兩次只是為了100%確定這個結論。