天天看點

docker容器間的聯網

翻譯自docker官方文檔,原文:https://docs.docker.com/engine/tutorials/networkingcontainers/

如果你是順着使用者指南讀到這的,那麼你剛剛建構并運作起來了一個簡單的應用。你也建構了你自己的鏡像。本節将教你如何讓你的容器通過網絡連接配接起來。

在預設網絡中啟動容器

docker支援通過網絡驅動器來将容器互聯。Docker預設提供兩種網絡驅動:bridge和overlay。你也可以自己寫一個網絡驅動插件來建立你自己的網絡驅動,但這是更高階的話題了。

Docker引擎安裝後預設就有三個網絡,你可以列出它們:

$ docker network ls

NETWORK ID          NAME                DRIVER
a2866682b8        none                null
c288470c46f6        host                host
b369448dccb        bridge              bridge
           

叫做bridge的網絡是特殊的,docker總是把你的容器加入這個網絡,除非你明确指定不要這樣做。嘗試下面的指令:

$ docker run -itd --name=networktest ubuntu

c9cea6d9810718fddadc01a727a5dd3ce6a69d09752239736c030599741
           
docker容器間的聯網

檢查(inspect)網絡是一種檢視容器IP位址的簡單方式:

$ docker network inspect bridge

[
    {
        "Name": "bridge",
        "Id": "f7ab26d71dbd6f557852c7156ae0574bbf62c42f539b50c8ebde0f728a253b6f",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.1/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
        "Internal": false,
        "Containers": {
            "3386a527aa08b37ea9232cbcace2d2458d49f44bb05a6b775fba7ddd40d8f92c": {
                "Name": "networktest",
                "EndpointID": "647c12443e91faf0fd508b6edfe59c30b642abb60dfab890b4bdccee38750bc1",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/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": {}
    }
]
           

你可以通過斷連接配接(disconnect)容器來把容器從一個網絡中移除。要做這件事,你要指定網絡名稱和容器名,也可以用容器ID代替。在本例中,用名字更快:

$ docker network disconnect bridge networktest
           

雖然你可以把一個容器從一個網絡中移除,但你不能移除内置的bridge式網絡“bridge”。網絡是把容器和其他容器或網絡進行隔離的原生的方式。是以,随着你使用docker的經驗增加,你會想要建立你自己的網絡的。

建立你自己的bridge式網絡

docker引擎原生就支援bridge式和overlay式的網絡。bridge式網絡隻能在運作docker引擎的單主機上運作。Overlay式網絡可以包含多個主控端并且是個更高階的話題。在本例中,你将建立一個bridge式網絡:

$ docker network create -d bridge my_bridge
           

-d标志告訴docker使用bridge驅動來建立新網絡。你也可以省略這個标志,因為bridge式這個标志的預設值。繼續并列出你機器上的所有網絡:

$ docker network ls

NETWORK ID          NAME                DRIVER
b369448dccb        bridge              bridge
d565d498c        my_bridge           bridge
a2866682b8        none                null
c288470c46f6        host                host
           

如果你檢查(inspect)剛建立的這個網絡,你會發現它裡面什麼也沒有:

$ docker network inspect my_bridge

[
    {
        "Name": "my_bridge",
        "Id": "5a8afc6364bccb199540e133e63adb76a557906dd9ff82b94183fc48c40857ac",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Config": [
                {
                    "Subnet": "10.0.0.0/24",
                    "Gateway": "10.0.0.1"
                }
            ]
        },
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
           

把容器加入網絡

要安全地建立多個需要通信的網絡應用,那就建立一個網絡。網絡,被定義成給容器提供完全的隔離。你可以在第一次啟動容器時就把它加入一個網絡。

啟動一個運作PostgreSQL資料庫的容器并傳

--net=my_bridge

參數給它,以使他連到你新建立的網絡上:

如果你檢查(inspect)你的my_bridge網絡,你會發現有一個容器附上了。你也可以檢查你的容器來檢視它連到那個網絡上了:

$ docker inspect --format='{{json .NetworkSettings.Networks}}'  db


{"my_bridge":{"NetworkID":"7d86d31b1478e7cca9ebed7e73aa0fdeec46c5ca29497431d3007d2d9e15ed99",
"EndpointID":"508b170d56b2ac9e4ef86694b0a76a22dd3df1983404f7321da5649645bf7043","Gateway":"10.0.0.1","IPAddress":"10.0.0.254","IPPrefixLen":,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":,"MacAddress":"02:42:ac:11:00:02"}}
           

現在,啟動你已經很熟悉的“web”應用。這次不要指定網絡:

docker容器間的聯網

你的”web”應用運作在哪個網絡下呢?檢查應用你就會發現它運作在預設的bridge網絡下:

$ docker inspect --format='{{json .NetworkSettings.Networks}}'  web


{"bridge":{"NetworkID":"7ea29fc1412292a2d7bba362f9253545fecdfa8ce9a6e37dd10ba8bee7129812",
"EndpointID":"508b170d56b2ac9e4ef86694b0a76a22dd3df1983404f7321da5649645bf7043","Gateway":"172.17.0.1","IPAddress":"10.0.0.2","IPPrefixLen":,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":,"MacAddress":"02:42:ac:11:00:02"}}
           

現在,擷取你的“web”應用的IP位址:

$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' web


172.17.0.2
           

現在,在正在運作的db容器中啟動一個shell:

$ docker exec -it db bash

[email protected]:/# ping 172.17.0.2
ping 
PING  () () bytes of data.
^C
--- 172.17.0.2 ping statistics ---
 packets transmitted,  received, % packet loss, time ms
           

等一會後按CTRL-C 來終止ping操作,你會發現ping失敗了。因為兩個容器在不同的網絡下運作着。你可以修複它。現在,用exit指令來關閉容器。

docker網絡允許你把一個容器連到多個網絡中。你也可以對正在運作的容器進行這種操作。現在把你的正在運作的“web”應用連到my_bridge上:

$ docker network connect my_bridge web
           
docker容器間的聯網

在db應用中啟動一個shell并在此嘗試ping操作。這次用容器名字“web”而不要用IP位址:

$ docker exec -it db bash

[email protected]:/# ping web
PING web () () bytes of data.
 bytes from web (): icmp_seq= ttl= time= ms
 bytes from web (): icmp_seq= ttl= time= ms
 bytes from web (): icmp_seq= ttl= time= ms
^C
--- web ping statistics ---
 packets transmitted,  received, % packet loss, time ms
rtt min/avg/max/mdev = /// ms
           

指令結果顯示它在連接配接一個不同的IP位址。Web容器在my_bridge中的IP位址和它在bridge網絡中的IP位址是不同的。

下一步

現在你知道了如何讓容器互聯,接下來請看如何管理容器中的資料。

譯者注:如上所示,在同一網絡内的兩個容器可以通過容器名來進行通信,但容器内的hosts檔案中并沒有配置容器名和容器IP間的映射關系,目前猜想是docker用來管理網絡的子產品實作了一種類似DNS服務的機制,維護了容器名和IP的映射關系,容器間的IP查找都通過該服務。另外,

docker run

指令中的

--link

參數的具體作用是什麼,也有待研究。