天天看點

Docker系列教程15-Docker容器網絡

原文: 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

ifconfig

指令浏覽Docker網絡,請前往 Docker Machine 檢視相關文檔;如您使用的是雲提供商,如AWS上的 或Digital Ocean上的 。可使用

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在兩種不同情況下自動建立的本地橋接網絡:

  • 當您初始化或加入swarm時,Docker會建立

    docker_gwbridge

    網絡,并将其用于不同主機上swarm節點之間的通信。
  • 當容器網絡不能提供外部連接配接時,除了容器的其他網絡之外,Docker将容器連接配接到

    docker_gwbridge

    網絡,以便容器可以連接配接到外部網絡或其他swarm節點。

如果您需要自定義配置,您可以提前建立

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

    --publish

    标志來釋出端口。 這告訴Docker在容器的網絡接口上打開哪些端口。當端口釋出時,它将映射到主控端上可用的高階端口(高于

    30000

    ),除非您在運作時指定要映射到主控端的哪個端口。 您不能在Dockerfile中指定要映射的端口,因為無法保證端口在運作image的主控端上可用。

    此示例将容器中的端口80釋出到主控端上的随機高階端口(在這種情況下為

    32768

    )。

    -d

    标志使容器在背景運作,是以您可以發出

    docker ps

    指令。
    $ 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
               
    下一個示例指定80端口應映射到主控端上的8080端口。 如果端口8080不可用,将失敗。
    $ 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
  1. 在Docker用戶端上,在啟動容器所使用的使用者的主目錄中建立或編輯

    ~/.config.json

    檔案。在其中添加如類似下所示的JSON,如果需要,使用

    httpsproxy

    ftpproxy

    替換代理類型,然後替換代理伺服器的位址和端口。 您可以同時配置多個代理伺服器。

    您可以通過将

    noProxy

    鍵設定為一個或多個逗号分隔的IP位址或主機名來選擇将指定主機或指定範圍排除使用代理伺服器。 支援使用

    *

    字元作為通配符,如此示例所示。
    {
      "proxies":
      {
        "httpProxy": "http://127.0.0.1:3001",
        "noProxy": "*.test.example.com,.example2.com"
      }
    }
               
    儲存檔案。
  2. 當您建立或啟動新容器時,環境變量将在容器内自動設定。

手動設定環境變量

在建構映像時,或在建立或運作容器時使用

--env

标志,可将下表中的一個或多個變量設定為适當的值。 這種方法使鏡像不太可移植,是以如果您使用Docker 17.07或更高版本,則應該配置Docker用戶端。

變量 Dockerfile示例

docker run

示例

HTTP_PROXY

ENV HTTP_PROXY "http://127.0.0.1:3001"

--env HTTP_PROXY "http://127.0.0.1:3001"

HTTPS_PROXY

ENV HTTPS_PROXY "https://127.0.0.1:3001"

--env HTTPS_PROXY "https://127.0.0.1:3001"

FTP_PROXY

ENV FTP_PROXY "ftp://127.0.0.1:3001"

--env FTP_PROXY "ftp://127.0.0.1:3001"

NO_PROXY

`ENV NO_PROXY "*.test.example.com,.example2.com"

-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

規則,這将非常有用。

相關資訊

繼續閱讀