Docker 網絡-端口映射、容器連接、Networking

在使用Docker容器時,咱們須要訪問容器的內部網絡,或須要在容器間相互訪問。Docker 容器默認不會開聽任何端口,所以須要將容器與宿主機進行端口映射,使容器可外部訪問。而容器間互相訪問,除了能夠基於端口映射進行訪問外,還能夠經過容器連接(Link)的方式,也能夠經過Docker 網絡(Networking)實現。html

  1. 端口映射與外部訪問容器python

    • 1.1 -P綁定宿主機隨機端口linux

    • 1.2 -p指定端口、IP地址綁定web

    • 1.3 其它docker

  2. 容器連接(Link)數據庫

    • 2.1 容器的命名express

    • 2.2 容器的互聯npm

  3. Docker網絡(Networking)安全

    • 3.1 建立網絡bash

    • 3.2 建立容器並鏈接到網絡

    • 3.3 將已有容器鏈接到Docker網絡

    • 3.4 斷開網絡與網絡刪除

1. 端口映射與外部訪問容器

Docker 容器運行後默認不會開啓任何網絡端口,這樣就沒法經過網絡訪問容器。要使容器能夠經過外部網絡訪問Docker 容器的內部網絡,就須要將容器端口與宿主機端口創建映射關係。

容器與宿主機間創建端口映射關係時,能夠在運行容器時使用-P-p參數指定端口映射。二者區別以下:

  • -P參數會隨機分配一個49000~49900之間的端口到容器內部開放的網絡(經過EXPORT指定的)端口

  • -p則能夠具體指定要映射的端口,而且在一個指定端口上只能綁定一個容器

 

1.1 -P綁定宿主機隨機端口

-P參數會隨機綁定一個49000~49900之間的端口所運行容器的導出端口。

如,運行一個容器,並使用-P綁定宿主機端口:

$ sudo docker run -d --name experss-app -P itbilu/express-app
28003e2dcdcd38075d1ad68d4791c77edaca47dc3d468b0333669ba483cd7b3d

在這個示例中,咱們經過itbilu/express-app鏡像建立並運行了一個名爲express-app的容器。運行容器時,咱們經過-P參數進行了端口映射。這時,能夠經過docker ps命令查看所分配的端口號:

$ sudo docker ps 
CONTAINER ID        IMAGE                COMMAND             CREATED             STATUS              PORTS                     NAMES
0781edb13563        itbilu/express-app   "npm start"         15 seconds ago      Up 14 seconds       0.0.0.0:32771->3000/tcp   experss-app

如上所示,宿主機的32771端口被綁定到了容器的3000端口。

 

1.2 -p指定端口、IP地址綁定

若是不想使用隨機端口,則可使用-p參數來指定要綁定的端口號。-p參數除了能夠指定端口號外,還能夠指定宿主機的IP,這一點在使用過程當中很是有用。

-p支持如下幾種綁定格式:

// 綁定宿主機IP及端口
ip:hostPort:containerPort
// 綁定宿主機IP
ip::containerPort
// 綁定宿主機端口
hostPort:containerPort

綁定宿主機全部的IP

使用hostPort:containerPort格式進行宿主機及容器端口映射時,默認會將宿主機的全部IP綁定到容器。如:

$ sudo docker run -d --name experss-app -p 3000:3000 itbilu/express-app

在這個示例中,將宿主機的3000端口映射到了容器的3000端口。在這種狀況下,會綁定本地全部接口上的全部IP地址。

映射到指定地址的指定端口

使用ip:hostPort:containerPort格式能夠將宿主機指定的IP及端口,綁定到容器端口。

如,綁定127.0.0.1IP到容器:

$ sudo docker run -d --name experss-app -p 127.0.0.1:3000:3000 itbilu/express-app

映射指定地址及隨機端口

ip::containerPort格式會綁定宿主機的指定IP地址及隨機端口到容器端口。如:

$ sudo docker run -d --name experss-app -p 127.0.0.1::3000 itbilu/express-app

使用docker ps查看所分配的端口:

$ sudo docker ps
CONTAINER ID        IMAGE                COMMAND             CREATED             STATUS              PORTS                       NAMES
6289a4714594        itbilu/express-app   "npm start"         4 seconds ago       Up 4 seconds        127.0.0.1:32768->3000/tcp   experss-app

 

1.3 其它

在前面示例中,咱們經過docker ps查看已建立的容器及容器所綁定的端口。除了docker ps命令外,還可使用docker port查看所綁定的端口及IP地址:

$ sudo docker port experss-app
3000/tcp -> 127.0.0.1:32768

容器內部可能會使用多個網絡端口,使用docker port命令時,能夠指定端口參數,以查看容器指定端口的綁定狀況:

$ sudo docker port experss-app 3000
127.0.0.1:32768

在建立/運行容器時,-p參數能夠被屢次使用,以綁定多個容器端口:

$ sudo docker run -d --name experss-app -p 3000:3000 -p 5000:80 itbilu/express-app

Docker進行端口綁定時,默認會綁定TCP端口。還可使用udp標記來綁定udp端口:

$ sudo docker run -d --name experss-app -p 3000:3000/udp itbilu/express-app

 

2. 容器連接(Link)

容器的鏈接(link)系統是除了端口映射外,另外一種跟容器中應用交互的方式。該系統會在源容器和接收容器之間建立一個隧道,接收容器能夠看到源容器指定的信息。Docker的連接是一個能夠將具體的容器鏈接到一塊兒來進行通訊的抽像層。

2.1 容器的命名

Docker的鏈接系統會依據容器的名稱來進行鏈接,所以,首先須要定義容器的名稱。在不指定容器命令的狀況,系統會隨機分配一個名稱。但相對來講,自定義容器名稱更容易記。

自定義容器名稱,可使用--name參數:

$ sudo docker run -d --name db training/postgres

命令並運行容器後,能夠經過docker ps命令來查看相關信息。也可使用docker inspect命令來查看容器的名稱:

$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
db2093b13127        training/postgres   "su postgres -c '/..."   4 seconds ago       Up 2 seconds        5432/tcp            db
$ sudo docker inspect -f "{{ .Name }}" db2093b13127
/db

 

2.2 容器的互聯

使用--link參數可讓容器間安全的進行互聯。

如,咱們能夠像下面這樣建立一個名爲web的容器,並將它鏈接到db容器:

$ sudo docker run -d -P --name web --link db:db training/webapp python app.py

這樣就在webdb之間創建了互聯關係。

--link參數格式

--link參數的格式爲--link name:alias,其中:name表示要鏈接的容器的名稱,而alias表示鏈接後的別名。

經過--link參靈敏,Docker 會在兩個互聯的容器之間建立了一個安全的隧道,且不用映射它們的端口到宿主主機上。在前面咱們啓動db容器的時,並無使用-p-P參數,從而避免了暴露數據庫端口到外部網絡上,增長了容器的安全性。

 

3. Docker網絡(Networking)

在Docker 1.9及以後,增長了Docker Networkingdocker network命令。容器之間的鏈接經過網絡來建立,這被稱爲Docker Networking

經過端口映射的方式開放容器的內部網絡,這種方式並不夠靈活、強大,且會暴露端口到外部網絡。容器連接和Dcoker Networking是更好的處理方式,Docker 1.9以前的版本推薦使用容器連接(Link)的方式,在Docker 1.9及以後則更推薦使用Dcoker Networking。相對連接來講,Networking具備如下優勢:

  • Dcoker Networking能夠將容器鏈接到不一樣宿主機上的容器

  • 經過Dcoker Networking鏈接的容器,能夠在不更新鏈接的狀況下對容器進行中止、啓動或重啓。而連接則須要經過更新配置,重啓對應的容器來更新容器之間的網絡

  • 使用Dcoker Networking能夠不用關心容器是否已運行,也不用關心容器的運行順序,而能夠在網絡內部獲取容器名的解析和發現

Docker 安裝會,有三個網絡會被自動建立。能夠經過docker network ls命令查看:

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
32dfd86b7900        bridge              bridge              local
18814c612f64        host                host                local
7914b1c3168c        none                null                local

在Docker歷史上,這三個網絡是Docker執行的一部分。在運行容器時,可使用--network指定要運行容器的網絡,面這三個網絡均可選。

3.1 建立網絡

Docker Networking容許用戶建立本身的網絡,容器間能夠經過這個網絡互相通信。Docker Networking容許容器跨越不一樣的宿主機通信,且網絡配置方式更靈活。

Docker Engine 會在引擎安裝時自動建立一個名爲bridge(橋接)網絡,這個網絡會與docker0(Docker內部網絡)相對應。

除此以外,用戶還能夠自行建立bridgeoverlay類型的網絡。bridge網絡適用於單臺宿主機運行的單Docker引擎環境,而overlay網絡容許咱們跨多臺宿主機進行通信。

要實現Docker Networking互聯,首先要使用docker network create命令建立一個網絡:

$ sudo docker network create my_network
32ddd24fd698665888ffa542215ae79a140b31ab3a10c96422ce2aee67b904a9

如上,咱們建立了一個名爲my_network的網絡,如今能夠經過docker network inspect查看這個新建的網絡:

$ sudo docker network inspect my_network
[
    {
        "Name": "my_network",
        "Id": "32ddd24fd698665888ffa542215ae79a140b31ab3a10c96422ce2aee67b904a9",
        "Created": "2017-04-04T04:05:13.230681143Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]

在不添加額外參數的狀況下,建立的是一個本地橋接網絡。而建立overlay網絡,須要預先存在一些條件,詳細官方文檔:Create networks

使用docker network ls命令也能夠看到這個新建的網絡:

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
32ddd24fd698        my_network          bridge              local
ae4ab5ad7602        bridge              bridge              local
18814c612f64        host                host                local
7914b1c3168c        none                null                local

 

3.2 建立容器並鏈接到網絡

建立網絡後,能夠在建立容器時經過--network參數指定容器要使用的網絡:

$ sudo docker run -d --name db --network=my_network training/postgres

使用docker network inspect查看的網絡狀況:

$ docker network inspect my_network
[
    {
        "Name": "my_network",
        "Id": "32ddd24fd698665888ffa542215ae79a140b31ab3a10c96422ce2aee67b904a9",
        "Created": "2017-04-04T04:05:13.230681143Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {
            "dccb4267650d8659e65aa3876ec6a427224111a91b4b253bb105af2295ad7a4a": {
                "Name": "db",
                "EndpointID": "6b1610e37eafbd044beb33f91f1d5d8e337da1b7376690f05b6fdeb0916edb9f",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

能夠看到my_network網絡的Containers參數中,包含了網建立的容器的信息,表中容器已鏈接到咱們所建立的網絡,而該容器的IP地址爲172.18.0.2

接下來,建立一個交互式容器,並查看該容器內部的網絡狀況:

$ sudo docker run -t -i --name web --network=my_network training/webapp /bin/bash
root@acb03a7adec2:/opt/webapp#

而後使用ping測試是否能夠鏈接到db容器:

# ping db
PING db (172.18.0.2) 56(84) bytes of data.
64 bytes from db.my_network (172.18.0.2): icmp_seq=1 ttl=64 time=0.136 ms
64 bytes from db.my_network (172.18.0.2): icmp_seq=2 ttl=64 time=0.092 ms
...

因而可知在同一網絡中的容器是能夠互相訪問的。

 

3.3 將已有容器鏈接到Docker網絡

當須要將已在運行的容器添加到已有的網絡時,可使用docker network connect命令。

刪除剛建立的web容器,並使用如下命令從新建立:

$ sudo docker run -d --name web training/webapp python app.py

將這個容器鏈接到已建立的名爲my_network的網絡:

$ sudo docker network connect my_network web

使用docker network inspect查看的網絡狀況,Containers節點內容以下:

...
"Containers": {
    "7258828bc9ab9153f060aa38c24daa63e22478632270172f5a1485e0e9a4797b": {
        "Name": "web",
        "EndpointID": "457fbf4ecebaabbe6cce2e95d7b1f47e35450897de3e6a00cde835cd3305eee9",
        "MacAddress": "02:42:ac:12:00:03",
        "IPv4Address": "172.18.0.3/16",
        "IPv6Address": ""
    },
    "dccb4267650d8659e65aa3876ec6a427224111a91b4b253bb105af2295ad7a4a": {
        "Name": "db",
        "EndpointID": "6b1610e37eafbd044beb33f91f1d5d8e337da1b7376690f05b6fdeb0916edb9f",
        "MacAddress": "02:42:ac:12:00:02",
        "IPv4Address": "172.18.0.2/16",
        "IPv6Address": ""
    }
}
...

一個容器能夠鏈接入多個網絡,從而構建出很是複雜的網絡模型。

 

3.4 斷開網絡與網絡刪除

還可使用docker network disconnect命令將容器與網絡斷開鏈接:

$ sudo docker network disconnect my_network web

這樣就將容器web與網絡my_network斷開的了鏈接。

網絡不在須要後,可使用docker network rm命令將網絡刪除:

$ sudo docker network rm my_network

注意:刪除網絡時,須要已斷開所容器的鏈接,不然會刪除失敗。

相關文章
相關標籤/搜索