探索本地Docker桥接网络

DockerOne 10年前

本文转自http://dockerone.com/article/137
我正在写《Docker in Action》(译者注:此书的样章可以在这里查看)第五章,内容有关Docker的容器连接与网络配置。最近一直在关注Docker的其它几个部分,我也重新熟悉了容器连接并深入研究了网络。

本文不会赘述我们已经熟悉的网络桥接。但是我猜很多使用Docker的开发者仍然不熟悉这部分内容,接下来我将为你展示容器启动的时候如何创建网络。下面我将会做一个实验,从几个容器中操作MongoDB。

启动目标容器

在这个实验中我们的目标是MongoDB数据库。你可以安装并使用以下命令启动MongoDB容器。
docker run --name some-mongo -d mongo:latest

启动另一个容器

这个容器基于Ubuntu镜像构建,运行了一个Shell环境。你可以检查你的本地网络并从这个容器连接到Mongo实例。
docker run -it --rm ubuntu:latest /bin/bash  root@XXX:/#

在交互模式下启动镜像,这样就可以安装你所需要的工具或者做其它事情而不会扰乱你的主机系统的状态。

获取您的命令行工具

你需要的工具包括Mongo CLI和nmap(译者注:nmap是网络探测工具和安全/端口扫描器)。
root@XXX:/#apt-get -y install nmap  root@XXX:/#apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10  root@XXX:/#echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list  root@XXX:/#apt-get update  root@XXX:/#apt-get install -y mongodb-org-shell

既然你正在以root身份运行的容器,你不用担心标准的sudo命令前缀。一旦这些命令运行完成,你就可以准备开启实验。

扫描网络

找到你的容器的IP地址,这样你就可以猜出你的目标可能在哪。
root@XXX:/#MY_IP=`/sbin/ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`

寻找在同一子网的监听端口为27017子网中的主机。执行此操作使用nmap进行子网的27017端口的扫描:
root@XXX:/#nmap -sS -p 27017 $MY_IP/24

在我的测试环境中的网络端口扫描的结果如下:
Starting Nmap 6.40 ( http://nmap.org ) at 2014-12-09 15:52 UTC  Nmap scan report for 172.17.0.33  Host is up (0.000030s latency).  PORT STATE SERVICE  27017/tcp closed unknown  MAC Address: 02:42:AC:11:00:21 (Unknown)  Nmap scan report for 172.17.0.34  Host is up (0.000021s latency).  PORT STATE SERVICE  27017/tcp closed unknown  MAC Address: 02:42:AC:11:00:22 (Unknown)  Nmap scan report for 172.17.0.96  Host is up (-0.079s latency).  PORT STATE SERVICE  27017/tcp open unknown  MAC Address: 02:42:AC:11:00:60 (Unknown)  Nmap scan report for 172.17.0.131  Host is up (-0.084s latency).  PORT STATE SERVICE  27017/tcp closed unknown  MAC Address: 02:42:AC:11:00:83 (Unknown)  Nmap scan report for XXX (172.17.0.132)  Host is up (0.000055s latency).  PORT STATE SERVICE  27017/tcp closed unknown  Nmap done: 256 IP addresses (5 hosts up) scanned in 4.10 seconds

从以上的输出中你可以看到,我的测试环境中运行的5个容器(包括一个正在运行命令的)。五个其中之一的端口27017是开放的。开放此端口的IP地址是运行你的MongoDB实例容器的IP地址。这是有趣的并且某些情况下可能会是一个惊喜,一会儿我就来聊聊这些。首先,让我们先做完实验。

访问数据库

使用先前安装的mongo CLI,你应该能够访问在其它容器中运行的MongoDB实例。在你得意忘形之前,你要知道这并不是Docker的或者Linux内核的漏洞,服务的端口是开放的,所以你肯定能正常访问。

当你配合IP地址运行以下命令,你可以看到输出:
root@XXX:/#mongo --host 172.17.0.96 # replace the IP address  MongoDB shell version: 2.6.6  connecting to: 172.17.0.96:27017/test  Welcome to the MongoDB shell.  For interactive help, type "help".  For more comprehensive documentation, see  http://docs.mongodb.org/  Questions? Try the support group  http://groups.google.com/group/mongodb-user  >_

就是这样。你可以在不同的容器内连接到MongoDB实例。获取对数据库的访问就是这么容易。惊讶吧?不应该。你正在运行一个没有身份验证要求的MongoDB实例。不要以为防火墙或网络拓扑会保护你的安全性差的服务。

Docker抽象化以及他们如何通信

此前在Docker的历险中,不知道为什么,我印象里网络是围绕着容器而构建。确实是这样。它们有分离接口的防火墙。不过我最初没有想到这些,即使是路由没有具体的链接。我认为,这是被Docker容器的链接增强了。

与其他人一样,当我学习如何访问其它容器的时候,首先使用的就是容器的连接。当你想连接另外一个已经存在的容器时,你可以在容器启动时通过参数指定(译者注:--link参数)。当你使用连接时,Docker会将IP和端口信息相关的环境变量放到新创建的容器。此外,其它的容器IP地址将会添加到/etc/hosts文件并对应容器的名称。(译者注:使用连接容器不需要公开端口,父容器可以直接访问子容器的公开端口,容器的端口不需要对宿主机公开,同时在容器中,会看到自动创建的一些环境变量,运行env命令试试。)

当我学习连接时,我停止了寻找其它的工具......至少一段时间。连接相当的方便,但他们只是提供了方便。他们告知你的新容器其他一些特定的容器的IP和端口信息。就是这样。桥接网络也没有什么花哨。

你可以访问其它容器的外部接口,就像他们是一个网络上的其它计算机。这应该是一件好事。我们知道该怎么做。

PS:别忘了停止并删除本实验中创建的容器。
docker kill some-mongo  docker rm -v some-mongo