Michael.W谈Docker 第四期-docker的网络
1 docker的端口映射
为什么需要端口映射?
加入一个客户端想要访问宿主机中的redis。如果redis是直接运行在宿主机中,可以直接访问宿主机的IP+redis的端口即可。但是如果redis是运行在docker容器中,那么就出问题了。由于容器是与外界隔离的,所以客户端根本访问不到容器。
这时,我们可以通过将容器的端口和宿主机的端口映射的方法,使得外界可以访问到容器中运行的redis。
用nginx来举例:
$ docker run ... -P ...
# -P为宿主机随机开放一个端口映射到nginx的80端口
$ docker run -itd --name nginx -P nginx
# 查看宿主机开放了哪个端口
$ docker ps
可见宿主机随机分配给容器的是32769端口。通过浏览器可以访问宿主机IP+32769端口:
可以从外部直接访问到宿主机中运行在容器中的nginx。
往往在开发中,我们都是用指定端口映射。参数使用-p:
$ docker run ... -p 宿主机端口:容器端口 ...
# 例子
$ docker run -itd --name mynginx -p 8888:80 nginx
宿主机把指定的8888端口与容器中的nginx做了映射。
注:在创建并启动nginx容器的时候,后边的[COMMAND]参数不需要写bash。上面的图可以看出来,容器在启动的时候自动执行了"nginx -g 'daemon of…"指令。如果写bash占位的话,会将这条指令替换掉。那么nginx将无法正常地被外界访问到。
还有一些常用的端口,作为常识要记住:
- http协议:使用端口:80
- https协议:使用端口:443
2 docker中的网络
输入ifconfig查看网络情况:
ens33位虚拟机的网卡信息,而上面的docker0就是docker安装后启动的一个默认网络。
网关是172.17.0.1,子网掩码是255.255.0.0(docker的子网掩码是16位),广播地址为172.17.255.255。
关于这个广播地址简单说两句。只要是udp通讯就可以进行广播,如果你电脑上的客户端监听以255结尾(最后一个段为255)的IP。而我是同一网段中的服务端,我只要向该网段的广播地址上持续发送数据,该网段中任何监听该地址的客户端都可以收到我发出来的数据。
广播的特点:不管客户端想不想收到我的数据,只要它开着客户端就一定会收到服务端向广播地址发送的所有数据。
话题扯回来。docker启动的容器就会自动连接到这个docker网络中(ip为172.17.0.x)。
2.1 查看docker中现有网络
$ docker network ls
执行 docker network ls 后,可以发现在docker中一共默认存在三种网络:
- bridge
- host
- none
none网络我就不去研究了,因为这个网络的所有属性都需要自己手动来配置。而birdge和host网络我在后面会有讲解。
# 查看当前bridge网络中的信息
$ docker inspect 网络名称
注意:这个172.17.0.x的网络对于外部是不可见的。
如何查看某个容器处于哪个网络中呢?
$ docker inspect 容器名
返回了一个很大的json对象,里面有一个"Networks"作为键的就是该容器所处的网络信息(显示信息为bridge网络,ip地址为172.17.0.2,没有IPv6地址等等)。
剩下的就去熟悉相关指令就好:
$ docker network COMMAND
# COMMAND包括
# connect 连接容器到指定的网络中
# create 创建一个网络
# disconnect 将容器从网络中删掉
# inspect 查看网络相关的信息
# ls 查看现有的所有网络
# prune 删除所有的未使用的网络(提醒!!)
# rm 删除一个或多个指定的网络
重要的事情要再强调一下:
指令docker network prune 一定不要因为好奇而去尝试使用!
2.2 bridge(桥接)网络
docker默认使用bridge网络,这个也推荐大家以后使用。bridge网络会虚拟出一个跟宿主机一样的网络环境,拥有自己的网段、网关、子网掩码等。
2.2.1 如何自己创建一个bridge类型网络?
$ docker network create [OPTIONS] NETWORK
有几个可选参数:
-d, --driver string 选择创建网络的驱动(就是选择你创建的网络类型是bridge,host或者none中的哪个),默认是bridge。
–gateway strings 你创建网络的IPv4或IPv6的网关
–subnet strings 用来设置创建网络的网段和子网掩码
例子:
docker network create --subnet 177.17.0.0/24 --gateway 177.17.0.1 mynet
可见docker网络中已经多了一个bridge类型的mynet,同时网络参数也是按照我们设置的那样。
输入ifconfig
可见此时已经已经虚拟好了一个新的网卡br-98a43197d19a。后面这串数字正好就是刚才我创建的mynet网络的网络ID。
2.2.2 如何在自定义网络中启动容器?
下面在我自定义创建的网络中启动容器:
$ docker run -itd ... --network 网络名 ...
只需要在以往启动容器的基础上加一个参数–network,后面接你创建的网络名。例子:
$ docker run -itd --name myubuntu --network mynet ubuntu bash
# 查看该容器的网络信息
$ docker inspect myubuntu
可见该容器运行在mynet网络中。
2.2.3 如何将容器断开自定义网络?
$ docker network disconnect [OPTIONS] 网络名 容器名
# 例子
$ docker network disconnetct mynet mybuntu
mynet网络中的容器已经为空,表名容器myubuntu已经与该网络断开连接。
2.2.4 如何将容器连接进自定义网络?
$ docker network connect [OPTIONS] 网络名 容器名
# 例子
$ docker network connect mynet myubuntu
当你启动一个容器的时候,如果不用–network指明,该容器会自动加入到默认的bridge网络中。
同时,一个容器是可以加入到多个网络中的!
如果一个容器要跟另一个容器通信,那么必须满足一个前提:
这些容器都必须处在同一个网络中。
2.3 host网络
host网络并不会像bridge网络一样虚拟出一个全新的网络环境,而是跟宿主机共用一个网卡,即在该网络中的容器跟宿主机使用相同的IP地址。
注意:host网络只能有一个,所以我是无法像bridge网络那样自己手动创建一个host类型的网络。
2.3.1 如何把一个容器加入到host网络中
一个容器是无法在创建之后再接入host网络和再从host网络中断开,比如
$ docker network connect host myubuntu
如果想要创建一个在host网络中的容器,那么只能在创建的时候直接创建在host网络中:
$ docker run -itd --name hostcon --network host ubuntu bash
# 查看hostcon容器的网络参数
$ docker inspect hostcon
可见,hostcon容器处在host网络中。尽管Gateway、IPAddress参数都是空,但是并不是表示没有,而是跟宿主机的网络参数一致。
ps:
本人热爱图灵,热爱中本聪,热爱V神,热爱一切被梨花照过的姑娘。
以下是我个人的公众号,如果有技术问题可以关注我的公众号来跟我交流。
同时我也会在这个公众号上每周更新我的原创文章,喜欢的小伙伴或者老伙计可以支持一下!
公众号名称:后现代泼痞浪漫主义奠基人