Tips: Docker网络配置
在配置CI环境里的Docker image时,走了一些坑,简记。
由于我们公司内网的Gitlab服务,域名是托管在内网的DNS上,通过公共的DNS无法解析。所以,在构建统一的Docker image时,发现在构建的image里无法连上内网的git server来pull代码,通过CI的Web终端,发现是因为我们的域名在Docker image里无法解析。
抛到脑海里的第一个想法便是,简单,那我就在我们的Docker image里,把hosts文件配置好:
docker run -i -t ci/ci-runner:v1 /bin/bash #进入docker image
echo '192.168.4.11 git.mycompany.com >> /etc/hosts'; #添加域名记录
exit
退出之后,把更新后的Docker image 提交到Docker Hub.
想着应该大功告成。结果,再次运行CI,发现还是同样的错误。这个时候,快速验证,再次进入ci/ci-runner这个image,打开hosts文件,发现,之前添加的记录消失了。
当时也没有多想,估计docker在启动image的时候,修改了hosts文件,多个docker之间通过compose相互访问,估计也是通过修改hostname以及hosts文件来实现的。所以,脑子里想着,估计行不通。也没有去立即读一下Docker关于网络部分文档,印入脑海的第二个方案便是,那不能改,也行,我在Docker里面起一个dns server,然后修改docker image里的 resolv.conf文件,让docker image使用内置的DNS服务总可以吧?
马上行动。然后在Docker image里面 安装了bind9 ,并配置了针对git.mycompany.com的解析。迅速的修改 /etc/resolvconf/resolv.conf.d/head 把配置好的DNS服务器的IP写进去。
退出image,提交更新到Docker Hub。再试,oh my god,还是同样的错误。ssh进入Docker image,发现,resolv.conf里并不包括我们创建的DNS服务器的IP地址。
在这个过程中,搜索研究了半天,看怎么持久化resolv.conf,结果,在非Docker环境下可行的方案,在Docker image里就是行不通。
最后,脑子里突然蹦出来,不会是Docker做了什么“坏事”,hosts不让改(docker只提倡通过docker命令启动image的时候添加hosts条目),DNS地址也有讲究吧?
打开 Docker官网 ,终于找到答案:
- hosts文件不能在image里面修改,是因为这个文件是通过动态mount进Docker image的
- DNS,默认从宿主主机上获取DNS,所以,如果修改好宿主的DNS,在其上启动的Docker image的DNS便会是修改好的DNS。
-
$$ mount /dev/disk/by-uuid/1fec...ebdf on /etc/hostname type ext4 ...