端口

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

参考:


本文访问量

本站总访问量

本站总访客数