docker容器內部端口映射到外部宿主機端口


相關內容原文地址:

博客園:散盡浮華:Docker容器內部端口映射到外部宿主機端口 - 運維筆記


Docker允許通過外部訪問容器或者容器之間互聯的方式來提供網絡服務。 容器啓動之後,容器中可以運行一些網絡應用,通過-p或-P參數來指定端口映射。 注意: - 宿主機的一個端口只能映射到容器內部的某一個端口上,比如:8080->80之後,就不能8080->81 - 容器內部的某個端口可以被宿主機的多個端口映射,比如:8080->80,8090->80,8099->80

1、啓動容器時,選擇一個端口映射到容器內部開放端口上

  1. -p 小寫p表示docker會選擇一個具體的宿主機端口映射到容器內部開放的網絡端口上。
  2. -P 大寫P表示docker會隨機選擇一個宿主機端口映射到容器內部開放的網絡端口上。
    比如:
[root@docker-test ~]# docker run -ti -d --name my-nginx -p 8088:80 docker.io/nginx
2218c7d88ccc917fd0aa0ec24e6d81667eb588f491d3730deb09289dcf6b8125
[root@docker-test ~]# docker run -ti -d --name my-nginx2 -P docker.io/nginx
589237ceec9d5d1de045a5395c0d4b519acf54e8c09afb07af49de1b06d71059
[root@docker-test ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                   NAMES
589237ceec9d        docker.io/nginx     "nginx -g 'daemon ..."   6 seconds ago        Up 5 seconds        0.0.0.0:32770->80/tcp   my-nginx2
2218c7d88ccc        docker.io/nginx     "nginx -g 'daemon ..."   About a minute ago   Up About a minute   0.0.0.0:8088->80/tcp    my-nginx

由上面可知:
容器my-nginx啓動時使用了-p,選擇宿主機具體的8088端口映射到容器內部的80端口上了,訪問http://localhost/8088即可
容器my-nginx2啓動時使用了-P,選擇宿主機的一個隨機端口映射到容器內部的80端口上了,這裏隨機端口是32770,訪問http://localhost/32770 即可。

2、啓動創建時,綁定外部的ip和端口(宿主機ip是192.168.10.214)

[root@docker-test ~]# docker run -ti -d --name my-nginx3 -p 127.0.0.1:8888:80 docker.io/nginx
debca5ec7dbb770ca307b06309b0e24b81b6bf689cb11474ec1ba187f4d7802c
[root@docker-test ~]# docker run -ti -d --name my-nginx4 -p 192.168.10.214:9999:80 docker.io/nginx
ba72a93196f7e55020105b90a51d2203f9cc4d09882e7848ff72f9c43d81852a
[root@docker-test ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                         NAMES
ba72a93196f7        docker.io/nginx     "nginx -g 'daemon ..."   2 seconds ago       Up 1 second         192.168.10.214:9999->80/tcp   my-nginx4
debca5ec7dbb        docker.io/nginx     "nginx -g 'daemon ..."   3 minutes ago       Up 3 minutes        127.0.0.1:8888->80/tcp        my-nginx3

由上面可知:
容器my-nginx3綁定的宿主機外部ip是127.0.0.1,端口是8888,則訪問http://127.0.0.1:8888或http://localhost:8888都可以,訪問http://192.168.10.214:8888就會拒絕!
容器my-nginx4綁定的宿主機外部ip是192.168.10.214,端口是9999,則訪問http://192.168.10.214:9999就可以,訪問http://127.0.0.1:9999或http://localhost:9999就會拒絕!

3、容器啓動時可以指定通信協議,比如tcp、udp

[root@docker-test ~]# docker run -ti -d --name my-nginx5 -p 8099:80/tcp docker.io/nginx
c08eb29e3c0a46386319b475cc95245ccfbf106ed80b1f75d104f8f05d0d0b3e
[root@docker-test ~]# docker run -ti -d --name my-nginx6 -p 192.168.10.214:8077:80/udp docker.io/nginx
992a48cbd3ef0e568b45c164c22a00389622c2b49e77f936bc0f980718590d5b
[root@docker-test ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                 NAMES
992a48cbd3ef        docker.io/nginx     "nginx -g 'daemon ..."   3 seconds ago       Up 2 seconds        80/tcp, 192.168.10.214:8077->80/udp   my-nginx6
c08eb29e3c0a        docker.io/nginx     "nginx -g 'daemon ..."   53 seconds ago      Up 51 seconds       0.0.0.0:8099->80/tcp                  my-nginx5

4、查看容器綁定和映射的端口及Ip地址

[root@docker-test ~]# docker port my-nginx5
80/tcp -> 0.0.0.0:8099
[root@docker-test ~]# docker inspect my-nginx5|grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.6",
                    "IPAddress": "172.17.0.6",

5、容器啓動綁定多IP和端口(跟多個-p)

[root@docker-test ~]# docker run -ti -d --name my-nginx8 -p 192.168.10.214:7777:80 -p 127.0.0.1:7788:80 docker.io/nginx
0e86be91026d1601b77b52c346c44a31512138cedc7f21451e996dd2e75d014d
[root@docker-test ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                 NAMES
0e86be91026d        docker.io/nginx     "nginx -g 'daemon ..."   17 seconds ago      Up 15 seconds       127.0.0.1:7788->80/tcp, 192.168.10.214:7777->80/tcp   my-nginx8

6、容器除了在啓動時添加端口映射關係,還可以通過宿主機的iptables進行nat轉發,將宿主機的端口映射到容器的內部端口上,這種方式適用於容器啓動時沒有指定端口映射的情況!

[root@docker-test ~]# docker run -ti -d --name my-nginx9 docker.io/nginx
990752e39d75b977cbff5a944247366662211ce43d16843a452a5697ddded12f
[root@docker-test ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS            NAMES
990752e39d75        docker.io/nginx     "nginx -g 'daemon ..."   2 seconds ago       Up 1 second         80/tcp           my-nginx9

這個時候,由於容器my-nginx9在啓動時沒有指定其內部的80端口映射到宿主機的端口上,所以默認是沒法訪問的!
現在通過宿主機的iptables進行net轉發

首先獲得容器的ip地址:

[root@docker-test ~]# docker inspect my-nginx9|grep IPAddress
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.9",
                    "IPAddress": "172.17.0.9",

[root@docker-test ~]# ping 172.17.0.9
PING 172.17.0.9 (172.17.0.9) 56(84) bytes of data.
64 bytes from 172.17.0.9: icmp_seq=1 ttl=64 time=0.105 ms
64 bytes from 172.17.0.9: icmp_seq=2 ttl=64 time=0.061 ms
.....

[root@docker-test ~]# telnet 172.17.0.9 80
Trying 172.17.0.9...
Connected to 172.17.0.9.
Escape character is '^]'

centos7下部署iptables環境紀錄(關閉默認的firewalle)
參考:http://www.cnblogs.com/kevingrace/p/5799210.html

將容器的80端口映射到dockers宿主機的9998端口:

[root@docker-test ~]# iptables -t nat -A PREROUTING -p tcp -m tcp --dport 9998 -j DNAT --to-destination 172.17.0.9:80
[root@docker-test ~]# iptables -t nat -A POSTROUTING -d 172.17.0.9/32 -p tcp -m tcp --sport 80 -j SNAT --to-source 192.16.10.214
[root@docker-test ~]# iptables -t filter -A INPUT -p tcp -m state --state NEW -m tcp --dport 9998 -j ACCEPT

保存以上iptables規則

[root@docker-test ~]# iptables-save > /etc/sysconfig/iptables

查看/etc/sysconfig/iptables文件,注意下面兩行有關icmp-host-prohibited的設置一定要註釋掉!否則nat轉發會失敗!

[root@docker-test ~]# cat /etc/sysconfig/iptables
# Generated by iptables-save v1.4.21 on Fri Aug 10 11:13:57 2018
*nat
:PREROUTING ACCEPT [32:1280]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -p tcp -m tcp --dport 9998 -j DNAT --to-destination 172.17.0.9:80
-A POSTROUTING -d 172.17.0.9/32 -p tcp -m tcp --sport 80 -j SNAT --to-source 192.16.10.214
COMMIT
# Completed on Fri Aug 10 11:13:57 2018
# Generated by iptables-save v1.4.21 on Fri Aug 10 11:13:57 2018
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [50:5056]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 9998 -j ACCEPT
#-A INPUT -j REJECT --reject-with icmp-host-prohibited
#-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
# Completed on Fri Aug 10 11:13:57 2018

最後重啓iptbales服務

[root@docker-test ~]# systemctl restart iptables

查看iptables規則

[root@docker-test ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:distinct32

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

[root@docker-test ~]# iptables -L -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DNAT       tcp  --  anywhere             anywhere             tcp dpt:distinct32 to:172.17.0.9:80

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
SNAT       tcp  --  anywhere             172.17.0.9           tcp spt:http to:192.16.10.214

然後訪問http://192.168.10.214:9998/,就能轉發訪問到my-nginx9容器的80端口了!!!

7、一次性刪除所有容器,包括正在運行的容器

[root@docker-test ~]# docker rm -f `docker ps -a -q`
990752e39d75
0e86be91026d
ff2bc46a8ee4
c08eb29e3c0a
ba72a93196f7
debca5ec7dbb
589237ceec9d
2218c7d88ccc

8、Docker 端口映射到宿主機後, 外部無法訪問對應宿主機端口

創建docker容器的時候,做了端口映射到宿主機, 防火牆已關閉, 但是外部始終無法訪問宿主機端口?
這種情況基本就是因爲宿主機沒有開啓ip轉發功能,從而導致外部網絡訪問宿主機對應端口是沒能轉發到 Docker Container 所對應的端口上。

解決辦法:
Linux 發行版默認情況下是不開啓 ip 轉發功能的。這是一個好的做法,因爲大多數人是用不到 ip 轉發的,但是如果架設一個 Linux 路由或者VPN服務我們就需要開啓該服務了。

在 Linux 中開啓 ip 轉發的內核參數爲:net.ipv4.ip_forward,查看是否開啓 ip轉發:

# cat /proc/sys/net/ipv4/ip_forward           // 0:未開啓,1:已開啓

打開ip轉發功能, 下面兩種方法都是臨時打開ip轉發功能!

# echo 1 > /proc/sys/net/ipv4/ip_forward
# sysctl -w net.ipv4.ip_forward=1

永久生效的ip轉發:

# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1

# sysctl -p /etc/sysctl.conf      // 立即生效

Linux 系統中也可以通過重啓網卡來立即生效 (修改sysctl.conf文件後的生效)

# systemctl restart network              //CentOS 7
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章