本文主要討論的是Docker容器(container)的端口設置,以下實驗參考自Sébastien Goasguen撰寫的Docker Cookbook (ISBN 978-1-491-91971-2)第三章Page71~Page72。

如果想在網路中訪問運行的容器,須爲其指定端口,在docker run命令中可使用-P(大寫)動態映射容器到宿主機的端口,也可使用-p(小寫)手動指定映射

docker run * -P, --publish-all: (大寫)Publish all exposed ports to random ports * -p, --publish=[]: (小寫)Publish a container’s port(s) to the host

Dynamically Map

使用P(大寫)動態配置端口映射

#大寫P
[flying@lemp ~]$ docker ps -qa
[flying@lemp ~]$ docker run -d -P --name nginxP nginx:latest
011492bf1e9fd87aa9203a1c328a321ceaad1c40681791b6a0b088e00217359d

#查看新啓動的容器信息
[flying@lemp ~]$ docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                           NAMES
011492bf1e9f        nginx:latest        "nginx -g 'daemon off"   13 seconds ago      Up 10 seconds       0.0.0.0:32779->80/tcp, 0.0.0.0:32778->443/tcp   nginxP

#查看容器ID
[flying@lemp ~]$ docker ps -ql
011492bf1e9f

#查看容器IP
[flying@lemp ~]$ docker inspect -f '{{.NetworkSettings.IPAddress}}' nginxP
172.17.0.2

#查看端口映射關係
[flying@lemp ~]$ docker port nginxP
443/tcp -> 0.0.0.0:32778
80/tcp -> 0.0.0.0:32779

#通過容器IP抓取header
[flying@lemp ~]$ curl -I 172.17.0.2
HTTP/1.1 200 OK
Server: nginx/1.9.14
Date: Fri, 15 Apr 2016 03:25:45 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 05 Apr 2016 15:20:43 GMT
Connection: keep-alive
ETag: "5703d7cb-264"
Accept-Ranges: bytes


#通過宿主機ip抓取header
[flying@lemp ~]$ curl -I 0.0.0.0:32779
HTTP/1.1 200 OK
Server: nginx/1.9.14
Date: Fri, 15 Apr 2016 03:26:26 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 05 Apr 2016 15:20:43 GMT
Connection: keep-alive
ETag: "5703d7cb-264"
Accept-Ranges: bytes

[flying@lemp ~]$

解釋0.0.0.0:32779->80/tcp: 宿主機監聽接口(interface)0.0.0.0,TCP端口(port)32779,轉發(forward)請求到容器(container)的端口80

Manually Map

手動指定端口

Both Host & Container

同時指定宿主機和容器的端口

[flying@lemp ~]$ docker run -d -p 7777:7777 --name nginx nginx:latest
7701f12547d7f63514271dabd20acc27e1d159506d04a275d4ec5f86b99c006c

#查看容器信息
[flying@lemp ~]$ docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                     NAMES
7701f12547d7        nginx:latest        "nginx -g 'daemon off"   7 seconds ago       Up 5 seconds        80/tcp, 443/tcp, 0.0.0.0:7777->7777/tcp   nginx

#查看容器id
[flying@lemp ~]$ docker ps -ql
7701f12547d7

#查看容器ip
[flying@lemp ~]$ docker inspect -f '{{.NetworkSettings.IPAddress}}' nginx
172.17.0.2

#查看端口映射
[flying@lemp ~]$ docker port nginx 80
Error: No public port '80/tcp' published for nginx

[flying@lemp ~]$ docker port nginx 443
Error: No public port '443/tcp' published for nginx

[flying@lemp ~]$ docker port nginx
7777/tcp -> 0.0.0.0:7777

#抓取header
[flying@lemp ~]$ curl -I 172.17.0.2
HTTP/1.1 200 OK
Server: nginx/1.9.14
Date: Fri, 15 Apr 2016 03:40:13 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 05 Apr 2016 15:20:43 GMT
Connection: keep-alive
ETag: "5703d7cb-264"
Accept-Ranges: bytes

#抓取header報錯
[flying@lemp ~]$ curl -I 0.0.0.0:7777
curl: (56) Recv failure: Connection reset by peer
[flying@lemp ~]$

Just for Container

Just TCP

爲容器指定端口12345(默認是TCP)

[flying@lemp ~]$ docker run -d -p 12345 --name nginxpt nginx:latest
6d031486e5bc1a71b2a43b7ceb250a0ce17e59cfcda6834bf3c5034e2058de40

#查看新啓動的容器信息
[flying@lemp ~]$ docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                       NAMES
6d031486e5bc        nginx:latest        "nginx -g 'daemon off"   20 seconds ago      Up 17 seconds       80/tcp, 443/tcp, 0.0.0.0:32779->12345/tcp   nginxpt

#查看容器id
[flying@lemp ~]$ docker ps -ql
6d031486e5bc

#查看容器ip
[flying@lemp ~]$ docker inspect -f '{{.NetworkSettings.IPAddress}}' nginxpt
172.17.0.2

#查看端口映射
[flying@lemp ~]$ docker port nginxpt 12345
0.0.0.0:32779

#抓取header
[flying@lemp ~]$ curl -I 172.17.0.2
HTTP/1.1 200 OK
Server: nginx/1.9.14
Date: Fri, 15 Apr 2016 03:30:57 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 05 Apr 2016 15:20:43 GMT
Connection: keep-alive
ETag: "5703d7cb-264"
Accept-Ranges: bytes

#抓取header報錯
[flying@lemp ~]$ curl -I 0.0.0.0:32779
curl: (56) Recv failure: Connection reset by peer
[flying@lemp ~]$

Both TCP & UDP

手動指定TCP、UDP端口

[flying@lemp ~]$ docker run -d -p 7777/tcp -p 8888/udp --name nginxtu nginx:latest
818f6647fb577a6feee4c4cd8476a22db276a62d5092bc2eecefc0615f3cb45f

#查看容器信息
[flying@lemp ~]$ docker ps -l
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                               NAMES
818f6647fb57        nginx:latest        "nginx -g 'daemon off"   21 seconds ago      Up 19 seconds       80/tcp, 443/tcp, 0.0.0.0:32780->7777/tcp, 0.0.0.0:32769->8888/udp   nginxtu

#查看容器id
[flying@lemp ~]$ docker ps -ql
c3f6aabee654

#查看容器ip
[flying@lemp ~]$ docker inspect -f '{{.NetworkSettings.IPAddress}}' nginxtu
172.17.0.3

#查看端口映射
[flying@lemp ~]$ docker port nginxtu 8888
Error: No public port '8888/tcp' published for nginxtu

[flying@lemp ~]$ docker port nginxtu 7777
0.0.0.0:32780
[flying@lemp ~]$

#抓取header
[flying@lemp ~]$ curl -I 172.17.0.3
HTTP/1.1 200 OK
Server: nginx/1.9.14
Date: Fri, 15 Apr 2016 03:35:06 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 05 Apr 2016 15:20:43 GMT
Connection: keep-alive
ETag: "5703d7cb-264"
Accept-Ranges: bytes

#抓取header報錯
[flying@lemp ~]$ curl -I 172.17.0.3:7777
curl: (7) Failed connect to 172.17.0.3:7777; Connection refused
[flying@lemp ~]$ curl -I 172.17.0.3:8888
curl: (7) Failed connect to 172.17.0.3:8888; Connection refused
[flying@lemp ~]$

#報錯
[flying@lemp ~]$ curl -I 0.0.0.0:32780
curl: (56) Recv failure: Connection reset by peer
[flying@lemp ~]$

執行sudo iptables -L,發現新增DOCKER

[flying@lemp ~]$ sudo iptables -L
...
...
...

Chain DOCKER (1 references)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             172.17.0.2           tcp dpt:italk
ACCEPT     udp  --  anywhere             172.17.0.3           udp dpt:ddi-udp-1
ACCEPT     tcp  --  anywhere             172.17.0.3           tcp dpt:cbt

Chain DOCKER-ISOLATION (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            
[flying@lemp ~]$

列出進程

[flying@lemp ~]$ ps -ef | grep docker
root     15430     1  0 07:58 ?        00:01:46 /usr/bin/docker daemon -H fd://
root     17950 15430  0 11:28 ?        00:00:00 docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 32779 -container-ip 172.17.0.2 -container-port 12345
root     24880 15430  0 11:33 ?        00:00:00 docker-proxy -proto udp -host-ip 0.0.0.0 -host-port 32769 -container-ip 172.17.0.3 -container-port 8888
root     24905 15430  0 11:33 ?        00:00:00 docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 32780 -container-ip 172.17.0.3 -container-port 7777
flying   31139 10755  0 11:37 pts/0    00:00:00 grep --color=auto docker
[flying@lemp ~]$

查看Docker網絡信息

[flying@lemp ~]$ docker network ls
NETWORK ID          NAME                DRIVER
51a4b74813e1        bridge              bridge              
1c43a0f654cc        none                null                
eb1e2b23446a        host                host                
[flying@lemp ~]$ docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "51a4b74813e1d78bf52ea086cdecd6904901d41152683a3a87b481f13b70b43c",
        "Scope": "local",
        "Driver": "bridge",
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16"
                }
            ]
        },
        "Containers": {
            "6d031486e5bc1a71b2a43b7ceb250a0ce17e59cfcda6834bf3c5034e2058de40": {
                "Name": "nginxpc",
                "EndpointID": "24552e362186d6abc267d4a8abaadc6f75b3c7a10945a9b46399ed9aaf3aa0df",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "818f6647fb577a6feee4c4cd8476a22db276a62d5092bc2eecefc0615f3cb45f": {
                "Name": "nginxtu",
                "EndpointID": "290ef7dad49c53bca4615db50d12c2b7d7b7fb2a0c00cff52aa8103a6a42f3ce",
                "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": "1500"
        }
    }
]
[flying@lemp ~]$

可以看到 * Docker默認會操作宿主機的IP table * Docker在宿主機上啓動一個小型代理(small proxy)監聽宿主機接口、動態選擇的端口

Relevant Questions


Change Log

  • 2016.04.15 11:50 Fri Asia/Beijing
    • 初稿完成

  • Note Time: 2016.04.15 11:50 Fri
  • Note Location: Asia/Beijing
  • Writer: lempstacker