前言
之前在用docker安装golang 版本的时候,有出现过一种情况,就是宿主机有设置代理,但在docker的容器内(container)下载golang依赖资源的时候,却不能使用宿主机的代理设置,所以下载依赖就会失败。
举个例子,我run了一个 docker 的容器,基于 go10.1 这个go版本。
1 | [root@VM_156_200_centos docker-go1.10]# sudo docker run -it --name golang-1.10-1 kbz/golang-1.10 |
然后我把宿主机的 go 程序的代码放到这个容器里面的 GOPATH 路径的 src 目录,最后跑起来,但是因为没有安装依赖,所以会报错:
1 | [root@VM_156_200_centos docker-go1.10]# docker cp /root/go/src/goworker golang-1.10-1:/go/src/ |
这时候我返回到 src,然后安装依赖,发现要挂代理才能下载
1 | root@4943d5f1558c:/go/src/goworker# cd ../ |
结果我检测了一下,发现在容器里面,竟然是没有代理的, 而退出到宿主机,确实有代理的, 宿主机代理设置具体看: CentOS7 配置 shadowsocks 全局代理
1 | root@4943d5f1558c:/go/src# curl cip.cc |
尝试方案
查了一下网上的教程:custom-docker-daemon-options
并且参照了一下网上的方案,也说可以这样设置?? 然后我跟着试了一下:
1 | [root@VM_156_200_centos docker-go1.10]# sudo mkdir -p /etc/systemd/system/docker.service.d |
刚开始是 设置为 127.0.0.1
1 | [root@VM_156_200_centos docker-go1.10]# systemctl show docker |grep 127.0.0.1 |
接下来进入到 docker 容器中:
1 | [root@VM_156_200_centos docker-go1.10]# docker start -ai golang-1.10-1 |
发现还是没有代理的情况??? 之后我改成用的是 docker 的虚拟网桥地址,主机上启动的Docker容器会连接到这个虚拟网桥上:
1 | [root@VM_156_200_centos ~]# ifconfig |
也就是 172.17.0.1, 改过来看看
1 | [root@VM_156_200_centos docker-go1.10]# systemctl show docker |grep 172.17.0.1 |
进入docker 容器里面:
1 | [root@VM_156_200_centos docker-go1.10]# docker start -ai golang-1.10-1 |
发现还是不行。
因为宿主机的 /etc/profile 有设置代理,所以容器里面,也设置一下,看看行不行, 反正试试看呗??
1 | root@f6f5b929b332:/app# vim /etc/profile |
发现容器内,都没有 vim 这个指令???
因为容器是一个简单的 ubuntu 系统,所以要安装一下:
1 | root@f6f5b929b332:/app# apt-get update |
这样子,就可以在容器里面进行 vim 指令了:
1 | root@f6f5b929b332:/app# vim /etc/profile |
这时候在容器里 curl 这个域名,发现端口都通不了,估计需要映射出来?? 而且还是没有代理
1 | root@f6f5b929b332:/app# curl 172.17.0.1 |
解决方法
后面又在官网找到另一篇教程:use-environment-variables
根据不同的docker版本,有两种方式:
If your container needs to use an HTTP, HTTPS, or FTP proxy server, you can configure it in different ways:
- In Docker 17.07 and higher, you can configure the Docker client to pass proxy information to containers automatically. - In Docker 17.06 and lower, you must set appropriate environment variables within the container. You can do this when you build the image (which makes the image less portable) or when you create or run the container.
因为我的 docker 版本的客户端是 1.13.1, 所以只能用下面那种方式:
1 | [root@VM_156_200_centos docker-go1.10]# docker version |
1 | [root@VM_156_200_centos docker-go1.10]# cat dockerfile |
重新 build 成 kbz/golang-1.10-2, 然后重新 run 一个容器出来:
1 | [root@VM_156_200_centos docker-go1.10]# sudo docker run -it --name golang-1.10-3 kbz/golang-1.10-2 |
试了一下,好像也不行??? 那只能是另一种方式,就是把 docker 升级到 17.07 及以上,通过: docker 升级到最新版,已经升级上来了,并且大于 17.07 了
1 | [root@VM_156_200_centos ~]# docker version |
1 | [root@VM_156_200_centos ~]# mkdir .docker |
然后重新 run 一个 容器看看, 镜像还是用之前的,
1 | [root@VM_156_200_centos ~]# docker run -it --name golang-1.10-1 kbz/golang-1.10 |
发现 8118 端口还是被拒绝了, 有可能是 8118 端口没有映射出去,考虑到 docker 默认的是 bridge 的网络模式,端口是要做转发映射的。
所以为了直接用宿主机的 ip 和 端口,我们换成用 host 的网络模式,让它可以跟宿主机共用一个 Network Namespace。
1 | [root@VM_156_200_centos ~]# docker run -it --net host --name golang-1.10-1 kbz/golang-1.10 |
这样子果然代理出去了。
那么如果把刚才那个代理的json配置文件去掉,是不是就会不能代理了???, 试试呗
1 | [root@VM_156_200_centos ~]# cd .docker/ |
把名字改掉,然后run 一个新的,看看:
1 | [root@VM_156_200_centos .docker]# docker run -it --net host --name golang-1.10-test kbz/golang-1.10 |
果然不能翻墙了。然后再把 json 文件重新改回来,再试试
1 | [root@VM_156_200_centos .docker]# mv config.json.bak config.json |
果然又可以代理了。
后面有出现了一个问题:我现在容器里面可以使用宿主机的代理了,但是我发现在宿主机使用 docker pull 下载镜像,会报错,但是进入容器,网络又正常?? 而且宿主机的网络也正常
1 | [root@VM_156_200_centos .docker]# docker pull centos |
后面查了一下,原来是之前我在进行尝试的时候,在docker的配置文件,增加了两个配置文件:
1 | [root@VM_156_200_centos .docker]# cd /etc/systemd/system/docker.service.d/ |
但是因为之前尝试失败,就放在那边,而且重装的时候,也一直还在,导致还一直在生效,所以这个要删掉才行,并且重启docker
1 | [root@VM_156_200_centos docker.service.d]# cd .. |
这样 docker pull 就正常了:
1 | [root@VM_156_200_centos system]# docker pull centos |
所以之后尝试失败的东西,一定要清干净!!!