簡介
我們安裝Docker后,它會自動創建三個網絡,bridge(創建容器默認連接到此網絡)、 none 、host。
- host:容器將不會虛擬出自己的網卡,配置自己的IP等,而是使用宿主機的IP和端口。
- None:該模式關閉了容器的網絡功能,相當於一個回環網絡。
- Bridge:此模式會為每一個容器分配、設置IP等,並將容器連接到一個叫docker0的虛擬網橋,通過docker0網橋以及Iptables nat表配置與宿主機通信。
關於上述提到的三個網絡解釋如下:
- Host:相當於Vmware中的橋接模式,與宿主機在同一個網絡中,但沒有獨立的IP地址。眾所周知,Docker使用了Linux的Namespaces技術來進行資源隔離,如PID Namespace隔離進程,Mount Namespace隔離文件系統,Network Namespace隔離網絡等。一個Network Namespace提供了一份獨立的網絡環境,包括網卡、路由、Iptable規則等都與其他的Network Namespace隔離。一個Docker容器一般會分配一個獨立的Network Namespace。但如果啟動容器的時候使用host模式,那么這個容器將不會獲得一個獨立的Network Namespace,而是和宿主機共用一個Network Namespace。容器將不會虛擬出自己的網卡,配置自己的IP等,而是使用宿主機的IP和端口。基於Host模式啟動的容器,在容器內執行ifconfig時,看到的都是宿主機上的信息。該模式不夠靈活,容易出現端口沖突問題。
- None:該模式將容器放置在它自己的網絡棧中,但是並不進行任何配置。實際上,該模式關閉了容器的網絡功能,類似於會換地址,在以下兩種情況下是有用的:容器並不需要網絡(例如只需要寫磁盤卷的批處理任務)。
- overlay:顧名思義:覆蓋,但它又不是覆蓋,它的作用就是在容器原有的網絡基礎之上,再添加一塊網卡,並為其分配一個IP地址,可以將所有的docker容器關聯到同一個局域網中,適用於容器與容器是跨主機進行通信的場景。
- Bridge:相當於Vmware中的NAT模式,容器使用獨立的network Namespace,並且連接到docker0虛擬網卡(默認模式)。通過docker網橋以及IPtables nat表配置與宿主機通信;Bridge模式是Docker默認的網絡設置,此模式會為每一個容器分配一個Network nameSpace、設置IP等,並將一個主機上的Docker容器連接到一個虛擬網橋docker0上。
Bridge如圖:
網絡模式使用總結
上面講了關於docker的網絡模式,主要關於以哪種方式讓服務器內部的容器與公網進行通信。
1、假如使用的是默認的橋接網絡模式,啟動容器的時候需要使用參數-p 宿主機端口:容器端口設置端口的映射。
2、假如使用的是host主機模式,因為使用的是宿主機的ip與端口,那就直接可以與公網通信。
相關命令
查看docker創建的網絡
#執行該命令查看docker創建的網絡
docker network ls
創建新網絡
docker network create <network-name>
將容器連接到網絡
docker run --net=<network-name> ...
或者將已存在容器加入新的網絡
docker network connect <network-name> <container-name>
按名稱ping容器
docker exec -ti <container-name-A> ping <container-name-B>
Ps:需要注意的是,如果容器沒有指定名稱(–name),那么就只能用id
啟動容器並指定模式
默認是Bridge
在容器啟動命令時用參數--net=host指定當前容器網絡模式
如:
docker run -itd --net=host centos:7 /bin/bash
查看容器元信息
docker inspect 容器ID
docker網絡連接命令介紹
docker network connect 命令是用於將docker容器連接到某個網絡中,或者與其他容器建聯,容器可以使用容器名或者容器ID。
用法
docker network connect [OPTIONS] NETWORK CONTAINER
選項
名稱,簡寫 | 默認 | 說明 |
---|---|---|
--alias |
為容器添加網絡范圍的別名 | |
--ip |
指定IP地址 | |
--ip6 |
指定IPv6地址 | |
--link |
添加鏈接到另一個容器 | |
--link-local-ip |
添加容器的鏈接本地地址 |
相關命令
命令名稱 | 說明 |
---|---|
docker network connect | 將容器連接到網絡 |
docker network create | 創建一個網絡 |
docker network disconnect | 斷開容器的網絡 |
docker network inspect | 顯示一個或多個網絡的詳細信息 |
docker network ls | 列出網絡 |
docker network prune | 刪除所有未使用的網絡 |
docker network rm | 刪除一個或多個網絡 |
docker默認Bridge內部通信
在實際的項目環境中,肯定會存在多個服務間通信的情況。也就是多個容器之間通信。
那么該如何通信呢?
它們都是通過默認的bridge
進行通信的。
啟動兩個centos7
docker run -itd --name centos1 centos:7
docker run -itd --name centos2 centos:7
查看兩個容器的元信息
主要是看虛擬ip
該命令會返回所有元信息
docker inspect 5c266f40400e
可以使用過濾並一次查詢兩個ip
docker inspect --format '{{ .NetworkSettings.IPAddress }}' 容器id1 容器id2
[root@localhost ~]# docker inspect --format '{{ .NetworkSettings.IPAddress }}' 5c266f40400e 861e6b2f0566
172.18.0.2
172.18.0.3
可以看到兩個容器虛擬ip分別為172.18.0.2
172.18.0.3
宿主機ping容器
[root@localhost ~]# ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.077 ms
64 bytes from 172.18.0.2: icmp_seq=3 ttl=64 time=0.054 ms
^C
--- 172.18.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.054/0.070/0.079/0.011 ms
[root@localhost ~]# ping 172.18.0.3
PING 172.18.0.3 (172.18.0.3) 56(84) bytes of data.
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.053 ms
64 bytes from 172.18.0.3: icmp_seq=2 ttl=64 time=0.052 ms
64 bytes from 172.18.0.3: icmp_seq=3 ttl=64 time=0.041 ms
^C
--- 172.18.0.3 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.041/0.048/0.053/0.009 ms
可以看到兩個都可以ping通
容器間互ping
開兩個ssh窗口
容器1
#進入容器
docker exec -it 5c266f40400e
[root@5c266f40400e /]# ping 172.18.0.3
PING 172.18.0.3 (172.18.0.3) 56(84) bytes of data.
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.072 ms
64 bytes from 172.18.0.3: icmp_seq=2 ttl=64 time=0.052 ms
^C
--- 172.18.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.052/0.062/0.072/0.010 ms
[root@5c266f40400e /]# ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.032 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.032 ms
^C
--- 172.18.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.032/0.032/0.032/0.000 m
容器2
#進入容器
docker exec -it 861e6b2f0566 /bin/bash
[root@861e6b2f0566 /]# ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.058 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.068 ms
^C
--- 172.18.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.058/0.063/0.068/0.005 ms
[root@861e6b2f0566 /]# ping 172.18.0.3
PING 172.18.0.3 (172.18.0.3) 56(84) bytes of data.
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.032 ms
64 bytes from 172.18.0.3: icmp_seq=2 ttl=64 time=0.022 ms
^C
--- 172.18.0.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.022/0.027/0.032/0.005 ms
總結
經過上面的測試你會發現宿主機,容器,容器和容器根據虛擬ip連通完全沒有問題
缺點
在docker中容器間直接通過ip進行服務訪問是存在弊端的。假如上面例子中某個centos容器突然掛掉重啟也失敗,只能重新run一個。這時ip可能會發生變化,那就需要進去直接修改相關配置信息,就很不友好。
解決辦法
因此Docker也提供了基於容器名來與其它容器通信。
docker基於容器名通信
容器之間若要通過容器名之間進行網絡通信,需要保證兩個容器在同一交換機下,且是在非默認的名為bridge
的交換機下.
所以在創建容器之前,需要新建一個交換機,網絡創建前,可以使用docker network ls
查看當前的交換機.。
創建網絡交換機
docker network create myNerwork
啟動兩個容器並指定網絡
docker run -itd --name centos3 --network=myNerwork centos:7
docker run -itd --name centos4 --network=myNerwork centos:7
進入網絡交換機中查看網絡信息
docker network inspect myNerwork
#返回
[
{
"Name": "myNerwork",
"Id": "c4fc8902df6c6343c56fe7966d4454cf0cee43a8ce9c843bbe1613b3232de98f",
"Created": "2021-01-06T16:35:32.8229922+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"04e723114d3fd9f92b50f37b960db168ffe7eb16302e36b257dcc52a78585caf": {
"Name": "centos4",
"EndpointID": "38002e89da4897edf1a27ebf57cf8723950a2e7c0e260c19fb99b8deb66ecc54",
"MacAddress": "02:42:ac:11:00:03",
"IPv4Address": "172.17.0.3/16",
"IPv6Address": ""
},
"5f7d789b38691678e0b9f0226b23f9839d9eb2ad4ece436d3e5db9d650ba5e3c": {
"Name": "centos3",
"EndpointID": "647a516fa3d579ee2f7031a3e0c06f2c29d50e9ca94696957d5ad5b8a60d6724",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
發現兩個容器都已經在新的網絡中了
測試容器使用容器名互ping
分別進入兩個容器
容器1
docker exec -it 5f7d789b3869 /bin/bash
[root@5f7d789b3869 /]# ping centos4
PING centos4 (172.17.0.3) 56(84) bytes of data.
64 bytes from centos4.myNerwork (172.17.0.3): icmp_seq=1 ttl=64 time=0.064 ms
64 bytes from centos4.myNerwork (172.17.0.3): icmp_seq=2 ttl=64 time=0.091 ms
64 bytes from centos4.myNerwork (172.17.0.3): icmp_seq=3 ttl=64 time=0.050 ms
64 bytes from centos4.myNerwork (172.17.0.3): icmp_seq=4 ttl=64 time=0.065 ms
64 bytes from centos4.myNerwork (172.17.0.3): icmp_seq=5 ttl=64 time=0.048 ms
^C
--- centos4 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3999ms
rtt min/avg/max/mdev = 0.048/0.063/0.091/0.017 ms
沒啥問題
容器2
docker exec -it centos4 /bin/bash
[root@04e723114d3f /]# ping centos3
PING centos3 (172.17.0.2) 56(84) bytes of data.
64 bytes from centos3.myNerwork (172.17.0.2): icmp_seq=1 ttl=64 time=0.044 ms
64 bytes from centos3.myNerwork (172.17.0.2): icmp_seq=2 ttl=64 time=0.066 ms
64 bytes from centos3.myNerwork (172.17.0.2): icmp_seq=3 ttl=64 time=0.094 ms
64 bytes from centos3.myNerwork (172.17.0.2): icmp_seq=4 ttl=64 time=0.084 ms
^C
--- centos3 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 0.044/0.072/0.094/0.019 ms
沒啥問題