Docker允許透過外部訪問容器或者容器之間互聯的方式來提供網路服務。
容器啟動之後,容器中可以執行一些網路應用,透過-p或-P引數來指定埠對映。
注意:
宿主機的一個埠只能對映到容器內部的某一個埠上,比如:8080->80之後,就不能8080->81
容器內部的某個埠可以被宿主機的多個埠對映,比如:8080->80,8090->80,8099->80
1)啟動容器時,選擇一個埠對映到容器內部開放埠上
-p
小寫p表示docker會選擇一個具體的宿主機埠對映到容器內部開放的網路埠上。
-P
大寫P表示docker會隨機選擇一個宿主機埠對映到容器內部開放的網路埠上。
1
2
3
4
5
6
7
8
9
10
11
12
13 |
比如: [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)
1
2
3
4
5
6
7
8
9
10
11
12 |
[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
1
2
3
4
5
6
7
8 |
[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地址
1
2
3
4
5
6 |
[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)
1
2
3
4
5 |
[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轉發,將宿主機的埠對映到容器的內部埠上, 這種方式適用於容器啟動時沒有指定埠對映的情況!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100 |
[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埠了!!! |
一次性刪除所有容器,包括正在執行的容器
1
2
3
4
5
6
7
8
9
10
11 |
[root@docker-
test
~]
# docker rm -f `docker ps -a -q` 990752e39d75 0e86be91026d ff2bc46a8ee4 c08eb29e3c0a ba72a93196f7 debca5ec7dbb 589237ceec9d 2218c7d88ccc [root@docker-
test
~]
# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES |
如果啟動docker 容器時,有如下報錯:
/usr/bin/docker-current: Error response from daemon: driver failed programming external connectivity on endpoint my-nginx (db5a0edac68d1ea7ccaa3a1e0db31ebdf278076ef4851ee4250221af6167f9ac): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 8088 -j DNAT --to-destination 172.17.0.2:80 ! -i docker0: iptables: No chain/target/match by that name.
解決辦法
1
2
3
4 |
1)不需要關閉防火牆 2)重啟docker服務:systemctl restart docker 3)docker服務重啟後,所有容器都會關閉,應立即批次啟動全部容器:docker start `docker
ps
-a -q`
啟動的容器也會包括上面報錯的容器,重啟docker後,該容器就能正常啟動和使用了! |
============ 問題: Docker 埠對映到宿主機後, 外部無法訪問對應宿主機埠==============
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 |
建立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檔案後的生效) # service network restart //CentOS 6 # systemctl restart network //CentOS 7 |