最近玩上了Docker,发现Docker确实可以节省很多繁杂的部署工作、提升工作效率。买了本《Docker入门与实践》,一边看一遍操作,学到了很多。在玩的过程中,遇到了 Docker DNS的问题,折腾了一段时间,想了各种方法,最终解决掉,这里记录下。
学习Docker 过程中,搭建了一个ReviewBoard代码评审系统,在添加代码仓库路径时,一直提示连接超时,获取不到代码,最后发现是容器的DNS服务器地址没有配置正确,默认是采用Google的DNS服务器8.8.8.8 这个地址,因为代码仓库路径的域名是内网域名,需要使用内网DNS服务器才能解析到,导致获取不到IP地址,把原来的域名服务器IP删掉修改成内网DNS服务器地址后(这里是采用echo xxxx > /etc/resolve.conf的方法),工作正常。
直接修改后是正常了,可是容器一旦重启,就又恢复原状,刚开始没弄清楚原理,折腾了很久:
1)开始以为这个配置文件是镜像的问题,就想到修改dockerfile尝试重新生成镜像,在生成镜像时将已经准备好的resolve.conf 添加到镜像中。结果失败了,发现添加进去后,域名服务器还是8.8.8.8,没有任何变化。搜索了下发现这个resolve.conf是挂载上去的。
2)既然文件覆盖不了,就想到在容器启动时在启动脚本中,增加执行动作,强制修改resolve.conf,理论上是可行的,但这样又要重新生成镜像,也很麻烦,不是好方法。
3)后来在搜索过程中,发现可以在创建容器时指定DNS 服务器地址,具体参数是 --dns=x.x.x.x 这样,比如docker run --dns=192.168.1.1 --name=server 。这样应该是可以的,不过最终也没有用这种方法,因为我的容器已经创建,不想把整个容器删掉重新来一遍。
4)最后一篇文章讲到,容器在启动时默认会使用宿主机的域名服务器配置文件(resolve.conf),会检查里面的域名服务器地址,过滤掉本地地址(127.0.0.1),如果过滤完后没有其他服务器地址,则自动添加Google的域名服务器地址作为容器的域名服务器地址,结果就出现了每次启动都是8.8.8.8的服务器地址。所以只要在宿主机的配置文件中新增你需要添加的服务器地址,然后重启下容器,容器中的域名服务器都会自动更新。经过验证,果然如此,重启下容器后,容器中的域名服务器配置都更新正确了。
总算是用一种比较简单的方法解决了这个问题。后来反思下:容器作为一种提升部署效率的新技术,不应该也不可能把一个小小的DNS服务器地址问题搞得这么复杂,设计者确实考虑的很周到,有各种方法来很简单的解决这个问题。是我没弄清楚原理,走了很多弯路,搞得这么复杂。