Docker容器内部端口映射到外部宿主机端口
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/nginx2218c7d88ccc917fd0aa0ec24e6d81667eb588f491d3730deb09289dcf6b8125[root@docker-test ~]# docker run -ti -d --name my-nginx2 -P docker.io/nginx589237ceec9d5d1de045a5395c0d4b519acf54e8c09afb07af49de1b06d71059[root@docker-test ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES589237ceec9d docker.io/nginx "nginx -g 'daemon ..." 6 seconds ago Up 5 seconds 0.0.0.0:32770->80/tcp my-nginx22218c7d88ccc 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 psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESba72a93196f7 docker.io/nginx "nginx -g 'daemon ..." 2 seconds ago Up 1 second 192.168.10.214:9999->80/tcp my-nginx4debca5ec7dbb 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/nginxc08eb29e3c0a46386319b475cc95245ccfbf106ed80b1f75d104f8f05d0d0b3e[root@docker-test ~]# docker run -ti -d --name my-nginx6 -p 192.168.10.214:8077:80/udp docker.io/nginx992a48cbd3ef0e568b45c164c22a00389622c2b49e77f936bc0f980718590d5b[root@docker-test ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES992a48cbd3ef docker.io/nginx "nginx -g 'daemon ..." 3 seconds ago Up 2 seconds 80/tcp, 192.168.10.214:8077->80/udp my-nginx6c08eb29e3c0a 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-nginx580/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/nginx0e86be91026d1601b77b52c346c44a31512138cedc7f21451e996dd2e75d014d[root@docker-test ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES0e86be91026d 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/nginx990752e39d75b977cbff5a944247366662211ce43d16843a452a5697ddded12f[root@docker-test ~]# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES990752e39d75 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.9PING 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 ms64 bytes from 172.17.0.9: icmp_seq=2 ttl=64 time=0.061 ms.....[root@docker-test ~]# telnet 172.17.0.9 80Trying 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.214COMMIT# 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-prohibitedCOMMIT# Completed on Fri Aug 10 11:13:57 2018最后重启iptbales服务[root@docker-test ~]# systemctl restart iptables查看iptables规则[root@docker-test ~]# iptables -LChain INPUT (policy ACCEPT)target prot opt source destination ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHEDACCEPT icmp -- anywhere anywhere ACCEPT all -- anywhere anywhere ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:sshACCEPT tcp -- anywhere anywhere state NEW tcp dpt:distinct32Chain FORWARD (policy ACCEPT)target prot opt source destination Chain OUTPUT (policy ACCEPT)target prot opt source destination [root@docker-test ~]# iptables -L -t natChain PREROUTING (policy ACCEPT)target prot opt source destination DNAT tcp -- anywhere anywhere tcp dpt:distinct32 to:172.17.0.9:80Chain 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`990752e39d750e86be91026dff2bc46a8ee4c08eb29e3c0aba72a93196f7debca5ec7dbb589237ceec9d2218c7d88ccc[root@docker-test ~]# docker ps -aCONTAINER 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 docker3)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.confnet.ipv4.ip_forward = 1# sysctl -p /etc/sysctl.conf // 立即生效Linux 系统中也可以通过重启网卡来立即生效 (修改sysctl.conf文件后的生效)# service network restart //CentOS 6# systemctl restart network //CentOS 7 |
Docker容器内部端口映射到外部宿主机端口的更多相关文章
- 从Docker容器内部,如何连接到本机的本地主机?
原文 从Docker容器内部,如何连接到本机的本地主机? 编辑:如果您使用的是Docker-for-mac或Docker-for-Windows 18.03+,只需使用主机连接到您的mysql服务即可 ...
- Docker容器内部端口映射到外部宿主机端口的方法小结
转自:https://www.cnblogs.com/kevingrace/p/9453987.html Docker允许通过外部访问容器或者容器之间互联的方式来提供网络服务.容器启动之后,容器中可以 ...
- Docker容器内部端口映射到外部宿主机端口 - 运维笔记
Docker允许通过外部访问容器或者容器之间互联的方式来提供网络服务.容器启动之后,容器中可以运行一些网络应用,通过-p或-P参数来指定端口映射. 注意:宿主机的一个端口只能映射到容器内部的某一个端口 ...
- docker容器添加对外映射端口
一般在运行容器时,我们都会通过参数 -p(使用大写的-P参数则会随机选择宿主机的一个端口进行映射)来指定宿主机和容器端口的映射,例如 docker run -it -d --name [contain ...
- 在宿主机上执行docker容器内部的shell或程序
为了避免反复进入docker容器内部操作,可以将一系列容器内部的指令由宿主机来操作完成. 在宿主机(作者主机为windows7)上执行centos容器(name为centos-1)中/usr目录下的“ ...
- Jenkins(4)docker容器内部修改jenkins容器时间
前言 用docker搭建的Jenkins环境时间显示和我们本地时间相差8个小时,需修改容器内部的系统时间 查看时间 查看系统时间 date-R 进入docker容器内部,查看容器时间 docker e ...
- Docker中运行MySQL5.7并挂载宿主机目录到镜像
原文:Docker中运行MySQL5.7并挂载宿主机目录到镜像 1.1 拉取mysql镜像 docker pull mysql:5.7 1.2 创建用于挂载的目录 mkdir -p /data/mys ...
- docker 端口映射 及外部无法访问问题
docker容器内提供服务并监听8888端口,要使外部能够访问,需要做端口映射. docker run -it --rm -p : server:v1 此时出现问题,在虚机A上部署后,在A内能够访问8 ...
- 如何进入到Docker容器内部
启动Docker容器后,对应的服务(例如tomcat启动)也通过dockerfile文件命令运行起来了,这个时候如何进行容器内部观察容器的运行状态. 1.docker attach 这个命令在创建一个 ...
随机推荐
- Cassandra commands
Common commands: describe keyspaces // 列出所有db use your_db; // 进去db describe tables; // 列出所有table ...
- 应用安全-CTF-格式串漏洞
主要影响c库中print家族函数 - > printf,sprintf,fprintf等 利用: SIP请求URI中格式串
- Eigen的aligned_allocator
今天看ORBSLAM2中的OptimizeEssentialGraph()函数时,对一句代码中的aligned_allocator不太清楚: vector<g2o::Sim3,Eigen::al ...
- Java8 HashMap详解(转)
Java8 对 HashMap 进行了一些修改,最大的不同就是利用了红黑树,所以其由 数组+链表+红黑树 组成. 根据 Java7 HashMap 的介绍,我们知道,查找的时候,根据 hash 值我们 ...
- python学习第四十八天json模块与pickle模块差异
在开发过程中,字符串和python数据类型进行转换,下面比较python学习第四十八天json模块与pickle模块差异. json 的优点和缺点 优点 跨语言,体积小 缺点 只能支持 int st ...
- asp.net 关于SessionId
原文:https://www.cnblogs.com/zhang1999/p/7278020.html 登陆页面使用Session存储验证码,导致会话产生SessionId,从而导致会话固定,登陆后用 ...
- ASP.NET Core 2.2 : 二十六. 应用JWT进行用户认证及Token的刷新
来源:https://www.cnblogs.com/FlyLolo/p/ASPNETCore2_26.html 本文将通过实际的例子来演示如何在ASP.NET Core中应用JWT进行用户认证以及T ...
- [好好学习]在VMware中安装Oracle Enterprise Linux (v5.7) - (1/5)
在想到Oracle Enterprise Linux,第一时间就是在Oracle官网上找到资源,但是,出现以下图片
- VirtualBox中安装CentOS 7
1.如下所示图,点击“新建”,创建一个新的虚拟机 2.类型选择Linux,版本选择Red Hat,下一步 3.分配内存大小,电脑8G内存,所以分给虚拟机2G,选择下一步 4.选择“现在创建虚拟硬盘” ...
- Altium Designer设计PCB中如何开槽
在不同层画槽孔形状实际得到的PCB效果(注意槽孔边缘) 在不同层画槽孔形状进行(注意槽孔边缘) 很多坛友问在使用Altium Designer设计PCB时,想在板子上开一个槽或者挖一个孔该如何操作,是 ...