Docker 端口 #
端口映射 #
-P
(大写):将容器内部开放的网络端口随机映射到宿主机的一个端口上-p
(小写):指定要映射的端口,一个指定端口上只可以绑定一个容器- 可以有多个
-p
- 可以有多个
端口映射格式 #
# 指定 ip、指定宿主机 port、指定容器 port
ip:hostport:containerport
# 指定 ip、未指定宿主机 port(随机)、指定容器 port
ip::containerport
# 未指定 ip、指定宿主机 port、指定容器 port
hostport:containerport
端口映射命令 #
# 将容器暴露的所有端口,都随机映射到宿主机上(不推荐)
docker run -P -it ubuntu /bin/bash
# 将容器指定端口随机映射到宿主机一个随机端口
docker run -P 80 -it ubuntu /bin/bash
# 将容器指定端口,随机映射到宿主机的指定 ip 的随机端口
# 有两个冒号 :
docker run -P 192.168.0.100::80 -it ubuntu /bin/bash
# 将容器指定端口指定映射到宿主机的指定端口上
docker run -p 8000:80 -it ubuntu /bin/bash
# 将容器指定端口,指定映射到宿主机指定 ip 和端口
# 只能访问 192.168.0.100:8000,
# 访问 127.0.0.1:8000 或 localhost:8000 都不行
docker run -p 192.168.0.100:8000:80 -it ubuntu /bin/bash
指定通信协议,比如 tcp、udp #
# tcp
docker run -ti -d --name my-nginx5 -p 8099:80/tcp docker.io/nginx
# udp
docker run -ti -d --name my-nginx6 -p 192.168.10.214:8077:80/udp docker.io/nginx
查看映射端口配置 #
# 结果输出: 80/tcp -> 0.0.0.0:800
docker port container_ID # 容器 ID
通过宿主机的 iptables 进行 nat 转发 #
容器除了在启动时添加端口映射关系,还可以通过宿主机的 iptables 进行 nat 转发,将宿主机的端口映射到容器的内部端口上, 这种方式适用于容器启动时没有指定端口映射的情况。
# 容器 my-nginx9 在启动时没有指定其内部的 80 端口映射到宿主机的端口上,
# 所以默认是没法访问的
docker run -ti -d --name my-nginx9 docker.io/nginx
# 首先获得容器的 ip 地址
docker inspect my-nginx9|grep IPAddress
# 将容器的 80 端口映射到 dockers 宿主机的 9998 端口
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 9998 -j DNAT --to-destination 172.17.0.9:80
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
iptables -t filter -A INPUT -p tcp -m state --state NEW -m tcp --dport 9998 -j ACCEPT
# 保存以上 iptables 规则
iptables-save > /etc/sysconfig/iptables
# 查看/etc/sysconfig/iptables 文件,
# 注意下面两行有关 icmp-host-prohibited 的设置一定要注释掉,否则 nat 转发会失败
# -A INPUT -j REJECT --reject-with icmp-host-prohibited
# -A FORWARD -j REJECT --reject-with icmp-host-prohibited
# 最后重启 iptbales 服务
systemctl restart iptables
# 查看 iptables 规则
iptables -L
# 然后访问 http://192.168.10.214:9998/,就能转发访问到 my-nginx9 容器的 80 端口了
问答 #
启动 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 文件后的生效
# CentOS 6
service network restart
# CentOS 7
systemctl restart network
参考:
叶王 © 2013-2024 版权所有。如果本文档对你有所帮助,可以请作者喝饮料。