暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Docker容器内部端口映射到外部宿主机端口

DevOps架构实战 2021-01-08
3827


docker允许通过外部访问容器或者容器之间互联的方式来提供网络服务。容器启动之后,容器中可以运行一些网络应用,通过-p或-P参数来指定端口映射。

注意:

宿主机的一个端口只能映射到容器内部的某一个端口上,比如:8080->80之后,就不能8080->81

容器内部的某个端口可以被宿主机的多个端口映射,比如:8080->80,8090->80,8099->80

(1)启动容器时,选择一个端口映射到容器内部开放端口上

-p   小写p表示docker会选择一个具体的宿主机端口映射到容器内部开放的网络端口上。

-P   大写P表示docker会随机选择一个宿主机端口映射到容器内部开放的网络端口上。

比如:

[root@docker ~]# docker run -ti -d --name my-nginx -p 8088:80 docker.io/nginx

2218c7d88ccc917fd0aa0ec24e6d81667eb588f491d3730deb09289dcf6b8125

[root@docker~]# docker run -ti -d --name my-nginx2 -P docker.io/nginx

589237ceec9d5d1de045a5395c0d4b519acf54e8c09afb07af49de1b06d71059

[root@docker ~]# 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.210.100)

[root@docker~]# docker run -ti -d --name my-nginx3 -p 127.0.0.1:8888:80 docker.io/nginx 

debca5ec7dbb770ca307b06309b0e24b81b6bf689cb11474ec1ba187f4d7802c

[root@docker~]# docker run -ti -d --name my-nginx4 -p 192.168.210.100:9999:80 docker.io/nginx              

ba72a93196f7e55020105b90a51d2203f9cc4d09882e7848ff72f9c43d81852a

[root@docker~]# 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.210.100: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.210.100:8888就会拒绝!

容器my-nginx4绑定的宿主机外部ip是192.168.210.100,端口是9999,则访问http://192.168.210.100:9999就可以,访问http://127.0.0.1:9999或http://localhost:9999就会拒绝!

(3)容器启动时可以指定通信协议,比如tcp、udp

[root@docker~]# docker run -ti -d --name my-nginx5 -p 8099:80/tcp docker.io/nginx

c08eb29e3c0a46386319b475cc95245ccfbf106ed80b1f75d104f8f05d0d0b3e

[root@docker~]# docker run -ti -d --name my-nginx6 -p 192.168.210.100:8077:80/udp docker.io/nginx

992a48cbd3ef0e568b45c164c22a00389622c2b49e77f936bc0f980718590d5b

[root@docker~]# 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.210.100: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~]# docker port my-nginx5

80/tcp -> 0.0.0.0:8099

[root@docker]# docker inspect my-nginx5|grep IPAddress

            "SecondaryIPAddresses": null,

            "IPAddress": "172.17.0.6",

                    "IPAddress": "172.17.0.6",

(5)容器启动绑定多IP和端口(跟多个-p)

[root@docker~]# docker run -ti -d --name my-nginx8 -p 192.168.210.100:7777:80 -p 127.0.0.1:7788:80 docker.io/nginx

0e86be91026d1601b77b52c346c44a31512138cedc7f21451e996dd2e75d014d

[root@docker ~]# 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.210.100:7777->80/tcp   my-nginx8

(6)容器除了在启动时添加端口映射关系,还可以通过宿主机的iptables进行nat转发,将宿主机的端口映射到容器的内部端口上,这种方式适用于容器启动时没有指定端口映射的情况

[root@docker~]# docker run -ti -d --name my-nginx9 docker.io/nginx

990752e39d75b977cbff5a944247366662211ce43d16843a452a5697ddded12f

[root@docker ~]# 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~]# docker inspect my-nginx9|grep IPAddress

            "SecondaryIPAddresses": null,

            "IPAddress": "172.17.0.2",

                    "IPAddress": "172.17.0.2",

[root@docker ~]# ping 172.17.0.2

PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.

64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.105 ms

64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.061 ms

.....

将容器的80端口映射到dockers宿主机的9998端口

[root@docker ~]# iptables -t nat -A PREROUTING -p tcp -m tcp --dport 9998 -j DNAT --to-destination 172.17.0.2:80

[root@docker~]# iptables -t nat -A POSTROUTING -d 172.17.0.2/32 -p tcp -m tcp --sport 80 -j SNAT --to-source 192.168.210.100

[root@docker~]# iptables -t filter -A INPUT -p tcp -m state --state NEW -m tcp --dport 9998 -j ACCEPT

 

保存以上iptables规则

[root@docker~]# iptables-save > etc/sysconfig/iptables

 

查看/etc/sysconfig/iptables文件,注意下面两行有关icmp-host-prohibited的设置一定要注释掉!否则nat转发会失败!

[root@docker-test ~]# cat etc/sysconfig/iptables

-A PREROUTING -p tcp -m tcp --dport 9998 -j DNAT --to-destination 172.17.0.2:80

-A POSTROUTING -d 172.17.0.2/32 -p tcp -m tcp --sport 80 -j SNAT --to-source 192.168.210.100

-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


最后重启iptbales服务

[root@docker ~]# systemctl restart iptables

 

查看iptables规则

[root@docker~]# 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~]# iptables -L -t nat

Chain PREROUTING (policy ACCEPT)

target     prot opt source               destination        

DNAT       tcp  --  anywhere             anywhere             tcp dpt:distinct32 to:172.17.0.2: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.2           tcp spt:http to:192.168.210.100

 

然后访问http://192.168.210.100:9998/,就能转发访问到my-nginx9容器的80端口了!!!


 

文章转载自DevOps架构实战,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论