1. 網絡模式
1.1 網絡結構
當安裝Docker以后,會自動創建三個網絡。可以使用docker network ls
命令列出這些網絡。
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
440aefe8afa3 bridge bridge local
aa8d6325580f host host local
3eb717ea6240 none null local
-
bridge
:橋接模式(默認),創建一個橋接網絡,內部網卡自動獲取IP地址,向外訪問是經過NAT(網絡地址轉換)。 -
host
:不會創建出自己的網卡,和宿主機共享網絡命名空間。即沒有自己的IP,而是使用宿主機的IP和端口。 -
none
:不配置網絡。需要時,進行自定義配置。
使用ip addr
查看系統網卡, 會多出一個網卡docker0
:
$ ip addr
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group defaultlink/ether 02:42:1d:9f:bd:cd brd ff:ff:ff:ff:ff:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft forever
brctl show
查看網橋,系統已經創建一個網橋:
$ brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02421d9fbdcd no
docker0
是一個網橋,可以把其他網卡加入,它工作在二層,可以理解是一個交換機
。每加入一個網卡,交換機便多一個口。
當創建一個Docker
容器的時候,同時會創建了一對veth pair
接口,兩個接口相當于用網線直連。 這對接口其中一個在容器內
;另一個被加入到docker0
網橋中,名稱以veth
開頭。
容器和主機可以通信,容器之間在一個局域里,也可以相互通信。Docker 創建了在主機和所有容器之間一個虛擬二層交換網絡。
【創建容器并運行】
docker run --name bjbook -p 8000:8000 -it --rm python:3 python -m http.server
這行命令使用 Docker 運行一個 Python 容器,并將其配置為一個簡單的 HTTP 服務器。
解釋:
docker run
: 運行一個 Docker 容器。--name bjbook
: 為容器命名為bjbook
。-p 8000:8000
: 將容器的 8000 端口映射到主機的 8000 端口。這意味著可以通過在瀏覽器中輸入http://localhost:8000
來訪問容器中的 HTTP 服務器。-it
: 以交互模式運行容器,并分配一個偽終端 (TTY)。這允許在容器中輸入命令。--rm
: 容器退出后自動刪除容器。python:3
: 使用 Python 3 鏡像作為容器的基礎鏡像。python -m http.server
: 在容器中運行 Python 的http.server
模塊,創建一個簡單的 HTTP 服務器。
【查看網橋】
brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02421d9fbdcd no vethd123cb3
發現網橋中增加了名稱為 vethd123cb3
的網卡。
【進入到容器里,查看其網卡信息】
$ docker exec -it bjbook bash
$ cat /proc/net/dev
$ cat /proc/net/fib_trie172.17.0.2/16
1.2 Bridge模式
bridge模式,–net=bridge
(默認)
這是docker網絡的默認設置,為容器創建獨立的網絡名字空間
,容器具有獨立的網卡
等所有單獨的網絡棧, 是最常用的使用方式。在docker run啟動容器的時候,如果不加–net參數,就默認采用這種網絡模式。
安裝完docker,系統會自動添加一個 供docker使用的網橋docker0,我們創建一個新的容器時,容器通過DHCP獲取一個與docker0同網段的IP地址
, 并默認連接到docker0網橋
,以此實現容器與宿主機的網絡互通。
【查看網絡信息】
$ docker network inspect bridge
[{"Name": "bridge","Id": "47b1606e07c37288c76ad42e2798ac60d836954bdd77b2167c10633b5ba7ad1a","Created": "2022-11-28T11:24:09.381326089+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": {},"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": {}}
]
1.3 Host模式
host模式,–net=host
和 - - network host
作用相同。
這個模式下創建出來的容器,直接使用容器宿主機的網絡名字空間
,例如網卡
和IP
都是和宿主機共用。 但容器的其他方面,如文件系統和進程等是和宿主機隔離的。
例如啟動nginx服務,默認綁定在主機的80端口,不用創建端口映射。
$ docker run --rm -d --network host --name my_nginx nginx1f378ca055340e87b3072e8cb15390c9b45a2b47ce4ebc8ec6dcfdec3e0503d5
1.4 Container模式
指定新創建的容器和已經存在的一個容器共享
一個 Network Namespace,而不是和宿主機共享。
新創建的容器不會創建自己的網卡,配置自己的 IP,而是和一個指定的容器共享 IP、端口范圍等。 這樣兩個容器除了網絡,其他的如文件系統和進程等是隔離的。兩個容器的進程可以通過 lo 網卡設備通信。
1.5 None模式
該模式Docker容器擁有自己的Network Namespace,但Docker容器沒有任何網絡配置
。
這個Docker容器沒有網卡、IP地址等
信息。按需另外為Docker容器添加網卡、配置IP等。
none模式可以在容器創建時通過–network=none
來指定。或使用 –net=none
指定。
應用舉例:
例如一些計算任務,寫入磁盤,不需要網絡的情況下使用。
2. 自定義網絡
2.1 容器互聯
在微服務部署的場景下,注冊中心是使用服務名
來唯一識別微服務的,而我們上線部署的時候微服務對應的IP地址可能會改動
,所以我們需要使用容器名來配置容器間的網絡連接。使用–link
可以完成這個功能。
首先不設置–link
的情況下,是無法通過容器名來進行連接的。centos02容器是可以直接ping通centos01的容器ip,但是無法ping通centos01的容器name:
[root@haha ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c742968a290a 5d0da3dc9764 "/bin/bash" 9 seconds ago Up 8 seconds centos02
581740709b5e 5d0da3dc9764 "/bin/bash" 30 seconds ago Up 28 seconds centos01
[root@haha ~]#
[root@haha ~]# docker exec -it centos01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft forever
34: eth0@if35: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group defaultlink/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever
[root@haha ~]#
[root@haha ~]# docker exec -it centos02 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.102 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.135 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.137 ms
[root@haha ~]#
[root@haha ~]# docker exec -it centos02 ping centos01
ping: centos01: Name or service not known
添加參數 –link
,可以通過容器name進行連接。centos03容器link到centos01,所以centos03可以直接通過ping centos01的容器名去ping通,但是反過來centos01去ping centos03的容器名是ping不通的。
[root@haha ~]# docker run -d -P -it --name centos03 --link centos01 5d0da3dc9764
a66f059fe26da45e5c59af03a2c33f429452a2dcf884ad5826fa0e3985ab3862
[root@haha ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a66f059fe26d 5d0da3dc9764 "/bin/bash" 7 seconds ago Up 5 seconds centos03
c742968a290a 5d0da3dc9764 "/bin/bash" 11 minutes ago Up 11 minutes centos02
581740709b5e 5d0da3dc9764 "/bin/bash" 11 minutes ago Up 11 minutes centos01
[root@haha ~]#
[root@haha ~]# docker exec -it centos03 ping centos01
PING centos01 (172.17.0.2) 56(84) bytes of data.
64 bytes from centos01 (172.17.0.2): icmp_seq=1 ttl=64 time=0.111 ms
64 bytes from centos01 (172.17.0.2): icmp_seq=2 ttl=64 time=0.074 ms
64 bytes from centos01 (172.17.0.2): icmp_seq=3 ttl=64 time=0.076 ms
^C
[root@haha ~]#
[root@haha ~]# docker exec -it centos01 ping centos03
ping: centos03: Name or service not known
–link
的原理就是在centos03容器的/etc/hosts
文件中添加了要去link的centos01容器的容器名和ip地址映射
。但是因為docker0不支持容器名訪問,所以–link設置容器互連的方式也不再推薦使用了,更多地選擇 自定義網絡
。
2.2 docker network命令
docker network
常使用的命令:
$ docker network --helpUsage: docker network COMMANDManage networksCommands:connect Connect a container to a networkcreate Create a networkdisconnect Disconnect a container from a networkinspect Display detailed information on one or more networksls List networksprune Remove all unused networksrm Remove one or more networks
創建網絡:
docker network create [OPTIONS] NETWORK_NAME
docker network create mynetwork
-d DRIVER
: 指定網絡驅動程序。--subnet SUBNET
: 指定網絡子網。--gateway GATEWAY
: 指定網絡網關。--ip-range IP_RANGE
: 指定網絡 IP 范圍。
連接網絡:
# 將容器連接到網絡
docker network connect [OPTIONS] NETWORK_NAME CONTAINER_NAME
docker network connect mynetwork mycontainer
--alias ALIAS
: 為容器分配一個別名。--ip IP_ADDRESS
: 為容器分配一個特定的 IP 地址。
斷開網絡:
# 將容器從網絡斷開
docker network disconnect [OPTIONS] NETWORK_NAME CONTAINER_NAME
docker network disconnect mynetwork mycontainer
刪除網絡:
docker network rm [OPTIONS] NETWORK_NAME
-f
: 強制刪除網絡,即使有容器連接到該網絡。
查看網絡:
docker network ls [OPTIONS]
-f
: 僅顯示正在使用的網絡。--filter
: 過濾網絡列表。
其他:
docker network inspect [OPTIONS] NETWORK_NAME
: 查看網絡的詳細信息。
一些額外的信息:
- 使用
docker network prune
命令刪除未使用的網絡。 - 使用
docker network update
命令更新網絡的配置。 - 使用
docker network create --help
命令查看更多選項。
2.3 自定義網絡
docker network create --helpOptions:--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 to copy 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
-d, --driver string
- 作用: 指定網絡驅動程序。
- 說明: 此選項指定用于創建網絡的網絡驅動程序。可用的驅動程序包括
bridge
、overlay
、macvlan
等。
–gateway strings
- 作用: 指定主子網的 IPv4 或 IPv6 網關。
- 說明: 此選項指定網絡的網關地址,用于路由到網絡外部的流量。
–subnet strings
- 作用: 指定 CIDR 格式的子網,表示網絡段。
- 說明: 此選項指定網絡的子網,用于分配容器 IP 地址。
示例:
[root@haha ~]$ docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
ed1c176a06d49da31969e229138ef5988a5fd9d2b2f2d2fc5ec1078be99a3d39
[root@haha ~]$ docker network ls
NETWORK ID NAME DRIVER SCOPE
aa8a26ae1484 bridge bridge local
62cd016ed66a host host local
ed1c176a06d4 mynet bridge local
fc650e2a675e none null local
查看新創鍵的mynet詳細信息:
使用自定義網絡創建容器后,相同網絡name下的容器,不管是通過容器IP還是容器name,都可以進行網絡通信:
# 創建兩個使用相同自定義網絡的容器
[root@haha ~]¥ docker run -d -P --name centos-net-01 --net mynet -it 5d0da3dc9764 /bin/bash
[root@haha ~]4 docker run -d -P --name centos-net-02 --net mynet -it 5d0da3dc9764 /bin/bash
[root@haha ~]$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2511566dd5f3 5d0da3dc9764 "/bin/bash" 4 seconds ago Up 3 seconds centos-net-02
924e92107f64 5d0da3dc9764 "/bin/bash" 23 seconds ago Up 21 seconds centos-net-01
a66f059fe26d 5d0da3dc9764 "/bin/bash" 43 minutes ago Up 43 minutes centos03
c742968a290a 5d0da3dc9764 "/bin/bash" 54 minutes ago Up 54 minutes centos02
581740709b5e 5d0da3dc9764 "/bin/bash" 55 minutes ago Up 55 minutes centos01# 測試容器互連
[root@haha ~]$ docker exec -it centos-net-01 ping centos-net-02
PING centos-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from centos-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.689 ms[root@haha ~]$ docker exec -it centos-net-01 ping 192.168.0.2
PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.091 ms
2.4 不同網卡的容器互聯
在沒有使用connect命令的情況下,不同網絡間的容器是無法進行網絡連接的。
不同Docker網絡之間的容器想要連接的話,需要把該容器注冊
到另一個容器所在的網絡上,使用docker connect
命令。
docker network connect mynet centos01
connect設置成功后,我們可以看到新注冊進來的容器信息:
連接測試:
# centos-net-01 ping centos01,連接成功
[root@haha ~]$ docker exec -it centos-net-01 ping centos01
PING centos01 (192.168.0.4) 56(84) bytes of data.
64 bytes from centos01.mynet (192.168.0.4): icmp_seq=1 ttl=64 time=0.183 ms# centos01 ping centos-net-01,連接成功
[root@haha ~]$ docker exec -it centos01 ping centos-net-01
PING centos-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.066 ms
64 bytes from centos-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.135 ms# 未連接到mynet的容器還是無法訪問
[root@haha ~]$ docker exec -it centos-net-01 ping centos02
ping: centos02: Name or service not known
參考鏈接:
Docker網絡詳解