前言 

本讲是从Docker系列讲解课程,单独抽离出来的一个小节,主要介绍容器间内部相互访问和外部访问容器的一些方法,它和前面两篇:容器五种(3+2)网络模式、容器之间单/双向通信 |--link /自定义网络知识点互补。

概述

通过对本文的学习,可以对docker run的-p -P两个参数,有个深入的了解,同时对容器间的访问也会有个深入的认识。这些基本功也会后期学好K8s做一些铺垫,从而打下一个坚实的基础。 

一、-p -P常见的五种使用方式

-p(小写)常用方式,多用于生产环境,格式:主机端口:容器端口

-P(大写)随机分配端口映射,多用于测试,宿主机会随机映射一个 49000~49900 的端口到映射容器内部的端口。

注:-d 参数 是后台静默运行,及时当前窗口关闭了,服务不会停止;sleep参数 ,指定容器后台阻塞运行N秒后自动销毁,想了解更多点击进入,第二章节第3小节。

1.宿主机随机端口映射容器所有端口

此处的所有端口,指的是自动匹配容器的内部端口。比如启动的是nginx自动匹配80,映射到80端口;容器是Tomcat,自动匹配8080端口,映射8080端口。


docker run -d --rm -P nginx:alpine  sleep 30  #注意:这里是大写的P (30s后,容器通过--rm自行销毁)
docker ps -a  #查看端口自动分配情况


docker pipeline插件 docker -p -p_容器

2.宿主机随机端口映射容器的指定端口


docker run -d --rm -p 80 nginx:alpine  sleep 30  #注意:这里是小写的p, 这个80是容器内的80端口
docker ps -a  #查看端口自动分配情况


docker pipeline插件 docker -p -p_nginx_02

3.宿主机指定端口映射容器指定端口(常用)


docker run -it -p 80:80 nginx /bin/bash
docker run -it -p 8080:80 nginx /bin/bash
docker run -it -p 443:443 nginx /bin/bash
docker run -it -p 80:80 -p 443:443 nginx /bin/bash   #给一个容器指定多个端口映射
docker run -it -p 80:80 -p 443:443 --restart=always   nginx    #容器出现异常,自尝试重新启动


4.宿主机指定IP+端口、映射容器指定端口


docker run -it -p 192.168.31.100:8080:80 nginx /bin/bash


5.宿主机指定IP+随机端口,映射容器指定端口


docker run -it -p 192.168.31.100::80 nginx /bin/bash


二、在容器外部访问容器 

访问原理:

需要把容器的内部端口,通过-p或-P做映射,从而把宿主机的端口暴露给外界,供外界访问,从而间接的访问到容器内部。

比如:docker run -p 8000:8080,后面的8080就是容器内部的端口,8000就是宿主机的端口,也是8080的映射端口,外界通过宿主机的8000端口来间接访问容器内部的8080端口。

理论总是有些绕口,看实战吧! 

1.示例1,通过-P做映射,外部浏览器访问容器


docker run -d -P --name mytomcat tomcat:8.5.46-jdk8-openjdk  #通过-P,主机随机端口映射容器端口
docker ps  #查看容器对外暴露端口和宿主机映射端口


在第一章节,已经提及,-P,宿主机会自动随机指定49000~49900内的一个端口,指向容器的内部端口,如下图所示:主机随机端口为49153,Tomcat容器内部的端口是8080。其中49153就是本实验要访问的宿主机端口。

宿主机IP是192.168.31.130,所以访问的地址应该是:192.168.31.130:49153

docker pipeline插件 docker -p -p_docker_03

发现,在物理机直接访问 192.168.31.130:49153是可以访问容器内部的Tomcat的。

docker pipeline插件 docker -p -p_docker pipeline插件_04

解析:表面访问的是 192.168.31.130:49153,实际访问的又是什么呢?实际访问的是虚拟机内部的tomcat容器内部的IP+容器内部的8080端口。

怎么查看容器的虚拟IP地址呢?通过docker inspect mytomcat就可以查看了。


docker inspect mytomcat #根据容器的别名,查看容器的详细信息,主要查看IP、端口


 

docker pipeline插件 docker -p -p_nginx_05

docker pipeline插件 docker -p -p_容器_06

由此,可以获悉容器的虚拟IP地址是172.17.0.2,内部访问端口是8080。

也就是说我们访问的: 192.168.31.130:49153,实际上访问的是172.17.0.2:8080

2.示例2,通过-p指定端口做映射,外部浏览器访问容器


docker run -d -p 5000:8080 --name cat  tomcat:8.5.46-jdk8-openjdk  #通过-p 指定主机端口映射容器指定端口
docker ps  #查看容器对外暴露端口和宿主机映射端口


docker pipeline插件 docker -p -p_运维_07

因为指定的宿主机端口是5000,所以下面用访问宿主机的IP+5000端口,访问容器内部的tomcat。

192.168.31.130:5000

 

docker pipeline插件 docker -p -p_容器_08

 

3.小节

上面介绍了-p和-P的常用的5种端口映射方式和外部浏览器访问容器的方法和步骤。下面一起来看一下,容器之间的相互访问吧!

三、容器访问容器 

访问原理:

同一宿主机的容器与容器之间除网络资源外(仅桥接模式和部分自定义网络模式下,网络互通),其他资源都是相互隔离。docker run 启动容器时,默认是使用的是桥接网络模式,在此模式下,在同一宿主机下的各容器可以通过对方容器的IP来进行访问。

如果使用自定义网络模式时-d bridge,容器之间可以通过别名相互访问。

1.使用桥接模式,容器间通过彼此IP访问


docker rm -f $(docker ps -qa)  #实验前,清空不相关容器,防止干扰下面的试验


1)docker run 分别启动nginx、tomcat两个容器


docker images  #查看镜像列表
docker run -d nginx:alpine   #使用默认网络模式(bridge)启动nginx
docker run -d -p 8080:8080 tomcat:8.5.46-jdk8-openjdk  #使用默认网络模式(bridge)启动tomcat


2)docker inspect分别查看两个容器的IP


docker ps #查看已启动容器列表
docker inspect 26d018333e00  #根据容器id查看nginx的网络信息(主要查看IP)
docker inspect f0f47e02ea8f  #根据容器id查看tomcat的网络信息(主要查看IP)


获悉nginx和tomcat的虚拟IP分别为172.17.0.2、172.17.0.3 

3)docker exec 分别进入容器内部nginx、tomcat两个容器相互通过IP访问对方

进入nginx容器内部,访问tomcat虚拟IP,发现可以访问通


docker exec -it 26d018333e00 /bin/sh  #进入nginx容器内部
ping -w 3 172.17.0.3  #尝试ping通tomcat服务器IP


 

docker pipeline插件 docker -p -p_容器_09

进入tomcat容器内部,访问nginx虚拟IP,发现可以访问通

docker pipeline插件 docker -p -p_docker_10

2.容器彼此之间除IP可以相互访问外,也可以通过容器别名相互访问

该章节的内容,在“容器之间单/双向通信”,一文中有详细介绍,可以点击进入了解一下。可以使用--link方式,也可以使用自定义网络模式,从而实现容器间通过别名相互访问。

下面就再简单介绍一下第二种方式(自定义网络模式)。


docker rm -f $(docker ps -qa)  #清空无关容器


1)自定义网络模式,命名为mynet


docker network ls  #先查看已有的网络模式
docker network create -d bridge mynet  #创建自定义网络,并指定为bridge桥接网络模式
docker network ls   #查看自定义的网络模式,是否创建成功


注:如果你想了解更多的docker network命令的使用,点击进入点击进入,查看最后的第五章节。 

docker pipeline插件 docker -p -p_容器_11


2)nginx和tomcat两个容器,在docker run 运行时,指定同一个自定义网络mynet


docker images  #查看已有镜像
docker run -d --name nginx  --net=mynet nginx:alpine   #指定网络为自定义网络mynet启动nginx
docker run -d --name tomcat --net=mynet -p 8080:8080 tomcat:8.5.46-jdk8-openjdk  #指定网络为自定义网络mynet启动tomcat


docker pipeline插件 docker -p -p_nginx_12


3)分别查看nginx和tomcat容器的虚拟IP


docker inspect nginx 
docker inspect tomcat


docker pipeline插件 docker -p -p_docker pipeline插件_13


docker pipeline插件 docker -p -p_运维_14


最终得知nginx和tomcat的虚拟ip分别是172.18.0.2 和 172.18.0.3

注:docker0虚拟网卡的默认网段是172.17,自定义网络mynet的网段和docker0的网段不能有重叠,默认是172.18。

在docker network create 时,可以通过--subnet指定网段(不使用默认的网段),感兴趣的话,点击进入,查看第三章节,当然,--subnet在docker run时也可以额外指定。

4) 分别进入nginx和tomcat容器内部,通过彼此的IP、别名相互访问


docker exec -it nginx sh  #进入nginx容器内部
ping -w 3 172.18.0.3  #ping tomcat的虚拟IP
ping -w 3 tomcat #ping tomcat的别名
exit

docker exec -it tomcat bash  #进入tomcat容器内部
ping -w 3 172.18.0.2  #ping nginx的虚拟IP
ping -w 3 nginx #ping nginx 的别名
exit


发现,通过自定义的网络模式(-d 指定为桥接)后,连接同一自定义网络的容器默认是可以通过别名相互访问的。

docker pipeline插件 docker -p -p_运维_15


5)小节

在容器内部访问同一宿主机的其他容器,默认只能通过其虚拟IP访问,是不识别对方容器的别名的。要想识别对方的别名,使用自定义网络模式,是不错的选择。

四、总结

1、无论是外部浏览器访问容器,还是容器间相互访问,容器都需要有各自的独立/共享(虚拟)ip,才可以( 桥接网络模式默认会为每一个容器单独分配虚拟的ip,Host网络模式的容器默认会共享宿主机的网络资源,host模式下的容器没有自己独立的ip,想了解更多,点击进入)。

2、同一宿主机下的容器,在桥接模式下模式是可以通过各自的虚拟ip,相互在容器内部访问;要想通过容器的别名相互访问,各容器,需要连接同一指定的自定义网络,来实现,更多详情,见容器间通过别名单/双向通信。

尾言

本讲是从 Docker入门到进阶系列里面抽离出来的内容,因为它是一个庞大的知识体系,一篇文章难以讲述清楚,也为了让原文根据层次分明,同时也可以加深自己对该知识点的理解,在此汇总分享给大家,希望对大家有所帮助。

如果觉得还不错,欢迎点赞,留言!

附注

最后,附注上你可能感兴趣的内容,送给爱学习的你,为你鼓掌、加油

1、Docker容器 | Dockerfile优化

2、Docker容器的生命周期 | kill和stop | pause 和 unpause

3、 Docker容器五种(3+2)网络模式 | bridge模式 | host模式 | none模式 | container 模式 | 自定义网络模式详解

4、容器之间单/双向通信 |--link /自定义网络实现互认容器别名

5、Docker核心命令 | 常用命令 | Docker build . 点的含义 | docker build和docker commit关系 | docker rm 与sleep用法_docker build --rm