原文: http://www.itmuch.com/docker/15-docker-network/
本文是篇翻譯。原文: https://docs.docker.com/engine/userguide/networking/
本節概述了Docker預設的網絡行為,包括預設情況下建立的網絡類型以及如何建立使用者自定義網絡。 本文也描述了在單個主機或叢集上建立網絡所需的資源。
有關Docker如何在Linux主機上與
iptables
進行互動的詳細資訊,請參閱
Docker和iptables
。
預設網絡
當您安裝Docker時,它會自動建立三個網絡,可使用
docker network ls
指令列出這些網絡:
$ docker network ls
NETWORK ID NAME DRIVER
7fca4eb8c647 bridge bridge
9f904ee27bf5 none null
cf03ee007fb4 host host
Docker内置如上三個網絡。 運作容器時,可使用
--network
标志來指定容器應連接配接到哪些網絡。
bridge
網絡代表所有Docker安裝中存在的
docker0
網絡。 除非您使用
docker run --network=<NETWORK>
選項,否則Docker守護程式預設将容器連接配接到此網絡。 可使用
ip addr show
指令(或簡寫形式,
ip a
),xia顯示該網橋的資訊。 (
ifconfig
指令已被棄用,根據系統的不同,還可能會
command not found
錯誤。)
$ ip addr show
docker0 Link encap:Ethernet HWaddr 02:42:47:bc:3a:eb
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:47ff:febc:3aeb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1
RX packets:17 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1100 (1.1 KB) TX bytes:648 (648.0 B)
如何在Docker for Mac或Docker for Windows上運作?
如果您使用Docker for Mac(或在Docker for Windows上運作Linux容器),
指令将按照上述方式工作,但
docker network ls
和
ip addr show
ifconfig
指令可能會展示結果,但會給你本地主機的IP位址資訊,而不是Docker容器網絡。 這是因為Docker使用虛拟機中運作的網卡,而并非在主控端的網卡。
要使用
或
ip addr show
指令浏覽Docker網絡,請前往 Docker Machine 檢視相關文檔;如您使用的是雲提供商,如AWS上的 或Digital Ocean上的 。可使用
ifconfig
登入到本地或雲托管的機器,也可根據雲提供商站點上的描述,直接
docker-machine ssh <machine-name>
ssh
none
網絡将容器添加到容器特定的網絡,該容器缺少網卡。Attach到一個網絡為
none
模式的容器,将會看到類似如下的内容:
$ docker attach nonenetcontainer
root@0cb243cd1293:/# 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
root@0cb243cd1293:/# ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
root@0cb243cd1293:/#
注意 :可使用 CTRL-p CTRL-q
斷開容器連接配接并離開。
host
網絡模式将容器添加到在主控端的網絡棧上。就網絡而言,主控端和容器之間沒有隔離。例如,如果您使用
host
網絡運作在80端口上運作一個Web伺服器容器,則該容器可在主控端的80端口上使用。
在Docker中,
none
host
網絡模式不能直接配置。 但是,您可以配置預設的
bridge
網絡,以及使用者自定義的網橋。
預設網橋
所有Docker主機上都有預設的
bridge
網絡。 如不指定網絡,容器将自動連接配接到預設的
bridge
網絡。
docker network inspect
指令傳回有關網絡的資訊:
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.17.0.1/16",
"Gateway": "172.17.0.1"
}
]
},
"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": "9001"
},
"Labels": {}
}
]
運作以下兩個指令啟動兩個
busybox
容器,兩個容器都連接配接到預設的
bridge
$ docker run -itd --name=container1 busybox
3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c
$ docker run -itd --name=container2 busybox
94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c
啟動兩個容器後再檢查
bridge
網絡。 這兩個
busybox
容器都連接配接到網絡。 可看到類似如下的結果:
$ docker network inspect bridge
{[
{
"Name": "bridge",
"Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.17.0.1/16",
"Gateway": "172.17.0.1"
}
]
},
"Containers": {
"3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c": {
"EndpointID": "647c12443e91faf0fd508b6edfe59c30b642abb60dfab890b4bdccee38750bc1",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
},
"94447ca479852d29aeddca75c28f7104df3c3196d7b6d83061879e339946805c": {
"EndpointID": "b047d090f446ac49747d3c37d63e4307be745876db7f0ceef7b311cbba615f48",
"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": "9001"
},
"Labels": {}
}
]
連接配接到預設
bridge
網絡的容器可通過IP位址進行通信。 Docker不支援在預設網橋上自動發現服務。如果您希望容器能夠通過容器名稱來解析IP位址,那麼可使用使用者自定義網絡 。您可以使用遺留的
docker run --link
選項将兩個容器連接配接在一起,但在大多數情況下不推薦使用。
您可以
attach
到正在運作的容器,檢視容器内部的IP是什麼。
$ docker attach container1
root@3386a527aa08:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02
inet addr:172.17.0.2 Bcast:0.0.0.0 Mask:255.255.0.0
inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1
RX packets:16 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1296 (1.2 KiB) TX bytes:648 (648.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
從容器内部,使用
ping
指令測試與其他容器的網絡連接配接。
root@3386a527aa08:/# ping -w3 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.096 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.080 ms
64 bytes from 172.17.0.3: seq=2 ttl=64 time=0.074 ms
--- 172.17.0.3 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.074/0.083/0.096 ms
使用
cat
指令檢視容器上的
/etc/hosts
檔案。 該指令顯示容器識别的主機名和IP位址。
root@3386a527aa08:/# cat /etc/hosts
172.17.0.2 3386a527aa08
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
要從
container1
容器離開,并保持容器的運作,請依次使用CTRL-p CTRL-q 。 如果你願意,也可attch到
container2
,并重複上面的指令。
預設的
docker0
橋接網絡支援使用端口映射和
docker run --link
,以便在
docker0
網絡中的容器之間進行通信。 不推薦這種方法。 如果可以,請使用
使用者定義的橋接網絡使用者自定義的網絡
建議使用使用者自定義網橋來控制哪些容器可以互相通信,這樣也可啟用自動DNS去解析容器名稱到IP位址。 Docker提供了建立這些網絡的預設網絡驅動程式。您可以建立一個新的橋接網絡, 覆寫網絡或MACVLAN網絡 。 您還可以建立一個網絡插件或遠端網絡進行完整的自定義和控制。
您可以根據需要建立任意數量的網絡,并且可在任意時間将容器連接配接到這些網絡中的零個或多個。 此外,您可以将運作着的容器連接配接或斷開網絡,而無需重新開機容器。當容器連接配接到多個網絡時,其外部連接配接通過第一個非内部網絡以詞彙順序提供。
接下來的幾節将詳細介紹Docker的内置網絡驅動程式。
網橋網絡
bridge
網絡是Docker中最常見的網絡類型。 橋接網絡類似于預設的
bridge
網絡,但添加一些新功能并删除一些舊的能力。 以下示例建立了橋接網絡,并對這些網絡上的容器執行一些實驗。
$ docker network create --driver bridge isolated_nw
1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b
$ docker network inspect isolated_nw
[
{
"Name": "isolated_nw",
"Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{
"Subnet": "172.21.0.0/16",
"Gateway": "172.21.0.1/16"
}
]
},
"Containers": {},
"Options": {},
"Labels": {}
}
]
$ docker network ls
NETWORK ID NAME DRIVER
9f904ee27bf5 none null
cf03ee007fb4 host host
7fca4eb8c647 bridge bridge
c5ee82f76de3 isolated_nw bridge
建立網絡後,您可以使用
docker run --network=<NETWORK>
選項啟動容器。
$ docker run --network=isolated_nw -itd --name=container3 busybox
8c1a0a5be480921d669a073393ade66a3fc49933f08bcc5515b37b8144f6d47c
$ docker network inspect isolated_nw
[
{
"Name": "isolated_nw",
"Id": "1196a4c5af43a21ae38ef34515b6af19236a3fc48122cf585e3f3054d509679b",
"Scope": "local",
"Driver": "bridge",
"IPAM": {
"Driver": "default",
"Config": [
{}
]
},
"Containers": {
"8c1a0a5be480921d669a073393ade66a3fc49933f08bcc5515b37b8144f6d47c": {
"EndpointID": "93b2db4a9b9a997beb912d28bcfc117f7b0eb924ff91d48cfa251d473e6a9b08",
"MacAddress": "02:42:ac:15:00:02",
"IPv4Address": "172.21.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
您啟動到此網絡的容器必須駐留在同一個Docker主機上。網絡中的每個容器可以立即與其他容器通信。 雖然網絡本身将容器與外部網絡隔離開來。
image
在使用者定義的橋接網絡中,不支援連結(link)。 您可以在此網絡中的容器上
暴露和釋出容器端口。 如果您希望使一部分
bridge
網絡可用于外部網絡,這将非常有用。
如果您希望在單個主機上運作相對較小的網絡,橋接網絡将非常有用。 但是,您可以通過建立
overlay
網絡來建立更大的網絡。
docker_gwbridge
網絡
docker_gwbridge
docker_gwbridge
是由Docker在兩種不同情況下自動建立的本地橋接網絡:
- 當您初始化或加入swarm時,Docker會建立
網絡,并将其用于不同主機上swarm節點之間的通信。docker_gwbridge
- 當容器網絡不能提供外部連接配接時,除了容器的其他網絡之外,Docker将容器連接配接到
網絡,以便容器可以連接配接到外部網絡或其他swarm節點。docker_gwbridge
如果您需要自定義配置,您可以提前建立
docker_gwbridge
網絡,否則Docker會根據需要建立它。 以下示例使用一些自定義選項建立
docker_gwbridge
$ docker network create --subnet 172.30.0.0/16 \
--opt com.docker.network.bridge.name=docker_gwbridge \
--opt com.docker.network.bridge.enable_icc=false \
docker_gwbridge
當您使用
overlay
網絡時,
docker_gwbridge
網絡始終存在。
swarm模式下的覆寫網絡
當Docker在swarm模式下運作時,您可以在管理節點上建立覆寫網絡,而無需外部key-value存儲。swarm使覆寫網絡僅可用于需要服務的swarm節點。 當您建立使用覆寫網絡的服務時,管理節點會自動将覆寫網絡擴充到運作服務任務的節點。
要了解有關在swarm模式下運作Docker Engine的更多資訊,請參閱
Swarm模式概述下面的示例顯示了如何建立網絡并将其用于來自swarm管理節點的服務:
$ docker network create \
--driver overlay \
--subnet 10.0.9.0/24 \
my-multi-host-network
400g6bwzd68jizzdx5pgyoe95
$ docker service create --replicas 2 --network my-multi-host-network --name my-web nginx
716thylsndqma81j6kkkb5aus
隻有swarm服務可以連接配接到覆寫網絡,而不是獨立的容器。 有關群集的更多資訊,請參閱
Docker swarm模式覆寫網絡安全模型以及
将服務附加到覆寫網絡非swarm模式下的覆寫網絡
如果您不是在swarm模式下使用Docker Engine,那麼
overlay
網絡需要有效的key-value存儲。 支援的key-value存儲包括Consul,Etcd和ZooKeeper(分布式存儲)。 在以這種方式建立網絡之前,您必須安裝并配置您所選擇的key-value存儲服務。 網絡中的Docker主控端、服務必須能夠進行通信。
注意 :以swarm模式運作的Docker Engine與使用外部key-value存儲的網絡不相容。
對于大多數Docker使用者,不推薦這種使用覆寫網絡的方法。它可以與獨立的swarm一起使用,可能對在Docker頂部建構解決方案的系統開發人員有用。 将來可能會被棄用。 如果您認為可能需要以這種方式使用覆寫網絡,請參閱
本指南自定義網絡插件
如果任何上述網絡機制無法滿足您的需求,您可以使用Docker的插件基礎架構編寫自己的網絡驅動插件。 該插件将在運作Docker deamon的主機上作為單獨的程序運作。 使用網絡插件是一個進階主題。
網絡插件遵循與其他插件相同的限制和安裝規則。 所有插件都使用插件API,并具有包含了安裝,啟動,停止和激活的生命周期。
建立并安裝自定義網絡驅動後,您可以使用
--driver
标志建立一個使用該驅動的網絡。
$ docker network create --driver weave mynet
您可以檢查該網絡、讓容器連接配接或斷開該網絡,删除該網絡。 特定的插件為特定的需求而生。 檢查插件文檔的具體資訊。 有關編寫插件的更多資訊,請參閱
擴充Docker 編寫網絡驅動程式插件内嵌DNS伺服器
Docker daemon運作一個嵌入式的DNS伺服器,進而為連接配接到同一使用者自定義網絡的容器之間提供DNS解析——這樣,這些容器即可将容器名稱解析為IP位址。 如果内嵌DNS伺服器無法解析請求,它将被轉發到為容器配置的任意外部DNS伺服器。 為了友善,當容器建立時,隻有
127.0.0.11
可通路的内嵌DNS伺服器會列在容器的
resolv.conf
檔案中。 有關在使用者自定義網絡的内嵌DNS伺服器的更多資訊,請參閱使用者定義網絡中的
暴露和釋出端口
在Docker網絡中,有兩種不同的機制可以直接涉及網絡端口:暴露端口和釋出端口。 這适用于預設網橋和使用者定義的網橋。
- 您使用
中的Dockerfile
關鍵字或EXPOSE
指令中的docker run
标志來暴露端口。 暴露端口是記錄使用哪些端口,但實際上并不映射或打開任何端口的一種方式。 暴露端口是可選的。--expose
- 您可以使用
Dockerfile
PUBLISH
docker run
标志來釋出端口。 這告訴Docker在容器的網絡接口上打開哪些端口。當端口釋出時,它将映射到主控端上可用的高階端口(高于--publish
30000
),除非您在運作時指定要映射到主控端的哪個端口。 您不能在Dockerfile中指定要映射的端口,因為無法保證端口在運作image的主控端上可用。
此示例将容器中的端口80釋出到主控端上的随機高階端口(在這種情況下為
)。32768
标志使容器在背景運作,是以您可以發出-d
指令。docker ps
下一個示例指定80端口應映射到主控端上的8080端口。 如果端口8080不可用,将失敗。$ docker run -it -d -p 80 nginx $ docker ps 64879472feea nginx "nginx -g 'daemon ..." 43 hours ago Up About a minute 443/tcp, 0.0.0.0:32768->80/tcp blissful_mclean
$ docker run -it -d -p 8080:80 nginx $ docker ps b9788c7adca3 nginx "nginx -g 'daemon ..." 43 hours ago Up 3 seconds 80/tcp, 443/tcp, 0.0.0.0:8080->80/tcp goofy_brahmagupta
容器與代理伺服器
如果您的容器需要使用HTTP、HTTPS或者FTP代理,你可以使用如下兩種方式進行配置:
- 對于Docker 17.07或更高版本,你可以配置Docker用戶端進而将代理資訊自動傳遞給容器。
- 對于Docker 17.06或更低版本,你必須在容器内設定環境變量。你可以在建構鏡像(這樣不太好移植)或啟動容器時執行此操作。
配置Docker用戶端
僅限Edge版本 :此選項僅适用于Docker CE Edge版本。 請參閱 Docker CE Edge
- 在Docker用戶端上,在啟動容器所使用的使用者的主目錄中建立或編輯
檔案。在其中添加如類似下所示的JSON,如果需要,使用~/.config.json
httpsproxy
ftpproxy
替換代理類型,然後替換代理伺服器的位址和端口。 您可以同時配置多個代理伺服器。
您可以通過将
鍵設定為一個或多個逗号分隔的IP位址或主機名來選擇将指定主機或指定範圍排除使用代理伺服器。 支援使用noProxy
字元作為通配符,如此示例所示。*
儲存檔案。{ "proxies": { "httpProxy": "http://127.0.0.1:3001", "noProxy": "*.test.example.com,.example2.com" } }
- 當您建立或啟動新容器時,環境變量将在容器内自動設定。
手動設定環境變量
在建構映像時,或在建立或運作容器時使用
--env
标志,可将下表中的一個或多個變量設定為适當的值。 這種方法使鏡像不太可移植,是以如果您使用Docker 17.07或更高版本,則應該配置Docker用戶端。
變量 | Dockerfile示例 | 示例 |
---|---|---|
| | |
| | |
| | |
| `ENV NO_PROXY "*.test.example.com,.example2.com" | |
連結
在Docker包含“使用者自定義網絡”功能之前,您可以使用Docker
--link
功能來允許容器将另一個容器的名稱解析為IP位址,還可以通路你所連結的容器的環境變量。 如果可以,您應該避免使用
--link
标志。
當您建立連接配接時,當您使用預設
bridge
或使用者自定義網橋時,它們的行為會有所不同。 有關詳細資訊,請參閱預設
bridge
連結功能的
遺留連結以及在
使用者自定義網絡中連結容器的連結容器Docker和iptables
Linux主機使用核心子產品
iptables
來管理對網絡裝置的通路,包括路由,端口轉發,網絡位址轉換(NAT)等問題。 Docker會在啟動或停止釋出端口的容器、建立或修改網絡、attach到容器或其他與網絡相關的操作時修改
iptables
規則。
對
iptables
全面讨論超出了本主題的範圍。 要檢視哪個
iptables
規則在任何時間生效,可以使用
iptables -L
。 如存在多個表,例如
nat
,
prerouting
postrouting
,您可以使用諸如
iptables -t nat -L
類的指令列出特定的表。 有關
iptables
的完整文檔,請參閱
netfilter / iptables通常,
iptables
規則由初始化腳本或守護程序建立,例如
firewalld
。 規則在系統重新啟動時不會持久存在,是以腳本或程式必須在系統引導時執行,通常在運作級别3或直接在網絡初始化之後運作。請參閱您的Linux發行版的網絡相關的文檔,了解如何使
iptables
規則持續存在。
Docker動态管理Docker daemon、容器,服務和網絡的
iptables
規則。 在Docker 17.06及更高版本中,您可以向名為
DOCKER-USER
的新表添加規則,這些規則會在Docker自動建立任何規則之前加載。 如果您需要在Docker運作之前預先設定需要使用的
iptables
規則,這将非常有用。