Docker容器内部端口映射到外部宿主机端口 - 运维笔记
Docker允许通过外部访问容器或者容器之间互联的方式来提供网络服务。
容器启动之后,容器中可以运行一些网络应用,通过-p或-P参数来指定端口映射。
注意:
宿主机的一个端口只能映射到容器内部的某一个端口上,比如:8080->80之后,就不能8080->81
容器内部的某个端口可以被宿主机的多个端口映射,比如:8080->80,8090->80,8099->80
1)启动容器时,选择一个端口映射到容器内部开放端口上
-p 小写p表示docker会选择一个具体的宿主机端口映射到容器内部开放的网络端口上。
-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端口了!!!
一次性删除所有容器,包括正在运行的容器
[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)重启docker服务:systemctl restart docker
3)docker服务重启后,所有容器都会关闭,应立即批量启动全部容器:docker start `docker ps -a -q`
启动的容器也会包括上面报错的容器,重启docker后,该容器就能正常启动和使用了!
============问题: 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文件后的生效)
# service network restart //CentOS 6
# systemctl restart network //CentOS 7
Docker容器内部端口映射到外部宿主机端口 - 运维笔记的更多相关文章
- Docker容器内部端口映射到外部宿主机端口的方法小结
转自:https://www.cnblogs.com/kevingrace/p/9453987.html Docker允许通过外部访问容器或者容器之间互联的方式来提供网络服务.容器启动之后,容器中可以 ...
- Docker容器内部端口映射到外部宿主机端口
Docker允许通过外部访问容器或者容器之间互联的方式来提供网络服务.容器启动之后,容器中可以运行一些网络应用,通过-p或-P参数来指定端口映射. 注意:宿主机的一个端口只能映射到容器内部的某一个端口 ...
- 教你如何修改运行中的docker容器的端口映射
在docker run创建并运行容器的时候,可以通过-p指定端口映射规则.但是,我们经常会遇到刚开始忘记设置端口映射或者设置错了需要修改.当docker start运行容器后并没有提供一个-p选项或设 ...
- [转帖]教你如何修改运行中的docker容器的端口映射
教你如何修改运行中的docker容器的端口映射 在docker run创建并运行容器的时候,可以通过-p指定端口映射规则.但是,我们经常会遇到刚开始忘记设置端口映射或者设置错了需要修改.当dock ...
- 如何修改运行中的docker容器的端口映射
在docker run创建并运行容器的时候,可以通过-p指定端口映射规则.但是,我们经常会遇到刚开始忘记设置端口映射或者设置错了需要修改.当docker start运行容器后并没有提供一个-p选项或设 ...
- 如何修改运行中的docker容器的端口映射和挂载目录
在docker run创建并运行容器的时候,可以通过-p指定端口映射规则.但是,我们经常会遇到刚开始忘记设置端口映射或者设置错了需要修改.当docker start运行容器后并没有提供一个-p选项或设 ...
- docker容器的端口映射
1.创建一个Nginx 容器,先不映射端口 [root@localhost ~]# docker run --name my_nginx -d nginx 7be3673a4c0f8f7ffe79a7 ...
- 修改docker容器的端口映射
大家都知道docker run可以指定端口映射,但是容器一旦生成,就没有一个命令可以直接修改.通常间接的办法是,保存镜像,再创建一个新的容器,在创建时指定新的端口映射. 有没有办法不保存镜像而直接修改 ...
- 修改已经创建的docker容器的端口映射
原始链接:https://stackoverflow.com/questions/19335444/how-do-i-assign-a-port-mapping-to-an-existing-dock ...
随机推荐
- LiveBOS Webservice初步使用
今天外部部门对接,需要我们这传输数据到他们的webservice,因为我是php的,他们java的demo没有参考意义,因此自己摸索着请求. 我使用的是php的扩展方法soap,首先new SoapC ...
- Mybatis逆向工程的使用。
指定配置文件与main运行生成 public class GeneratorSqlmap { public void generator() throws Exception { List<St ...
- Jenkins 显示语言-英文切换中文
1.进入插件管理 搜索 Locale 插件并进行安装 2.插件安装成功后进入系统设置 3.在 Locale 中 Default Language 字段填入 zh_CN 并且勾选 Ignore brow ...
- js 实现watch监听数据变化
1.js /** * @desc 属性改变监听,属性被set时出发watch的方法,类似vue的watch * @author Jason * @study https://www.jianshu.c ...
- Robot Framework常用关键字
虽然通过RIDE提供"填表"一样的写测试用例的方式.但它却支持强大的关键字功能,以及可以开发关键字的扩展能力. Comment 注释功能,也可以使用python中的"#& ...
- Robot Framework RIDE简单使用
Testproject Testsuite Testcase 1.创建测试项目 打开RIDE,点击File--New Project,选择项目路径,填入项目名称 2.右键点击新建的测试项目,选择New ...
- 线上IIS应用程序池自动关闭
事情的经过是这样的: 下午下班的铃声已经敲响,我已经整装待发.突然同事说某水司的微信公众号不能正常访问了.点击营业厅,直接提示Service Unavailable. 立马远程服务器查看,IIS微信公 ...
- IntelliJ idea SpringBoot打war包
简单易用的使用idea 将SpringBoot工程打war包的方法 pom.xml中添加标签 1. 声明打包格式 <packaging>war</packaging> 2. ...
- ARM开发板上查看动态库或者可执行程序的依赖关系
以ARM32开发板为例,在/lib下有一个名为ld-linux-armhf.so.3的可执行程序(在ARM64开发板上是/lib/ld-linux-aarch64.so.1),这个程序负责加载可执行程 ...
- 201871010128-杨丽霞《面向对象程序设计(java)》第四周学习总结
201871010128-杨丽霞<面向对象程序设计(java)>第四周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh 这个 ...