如何从Docker in Docker创建的容器中访问HTTP代理
问题根因
你当前的部署方案本质是 DooD(Docker outside of Docker) 而非真正的Docker in Docker:你把宿主机的/var/run/docker.sock挂载进外层Pod,所以在外层Pod内执行的所有docker命令,本质都是调用宿主机的Docker daemon来创建、管理容器,新启动的容器直接运行在Kubernetes worker节点上,和外层Pod是同级的节点本地容器,并不运行在外层Pod的网络命名空间内。
外层Pod可以正常使用代理,是因为你给外层Pod配置了代理环境变量,且Pod的网络可以正常连通代理服务器。但新启动的容器默认走宿主机Docker的bridge网络,和外层Pod的网络完全隔离,哪怕你手动在容器内配置了代理环境变量,也会因为网络层面无法连通代理服务器,导致无法访问公网。
解决方案
方案1:启动容器时共享外层Pod网络栈+注入代理变量
直接让新启动的容器共享外层Pod的网络命名空间,完全复用外层Pod的网络环境,同时把外层的代理变量直接注入新容器即可:
# 在外层Pod内执行,外层Pod的1号进程PID对应自身的网络命名空间 docker run -it --rm \ -e HTTP_PROXY=$HTTP_PROXY \ -e HTTPS_PROXY=$HTTPS_PROXY \ -e NO_PROXY=$NO_PROXY \ --network=container:1 \ alpine:3 sh
如果你的代理服务部署在宿主机本地,也可以将新容器的网络模式改为host,直接连通宿主机网络:
docker run -it --rm \ -e HTTP_PROXY=http://你的代理地址:端口 \ -e HTTPS_PROXY=http://你的代理地址:端口 \ -e NO_PROXY=无需代理的地址段 \ --network=host \ alpine:3 sh
方案2:给宿主机Docker daemon配置全局代理
因为你调用的是宿主机的Docker daemon,你可以直接在Kubernetes worker节点上配置Docker全局代理,所有通过该daemon创建的容器都会自动注入代理配置:
- 创建Docker服务配置目录
mkdir -p /etc/systemd/system/docker.service.d
- 新建代理配置文件
/etc/systemd/system/docker.service.d/http-proxy.conf
[Service] Environment="HTTP_PROXY=http://你的代理地址:端口" Environment="HTTPS_PROXY=http://你的代理地址:端口" Environment="NO_PROXY=无需代理的地址段"
- 重启Docker服务生效
systemctl daemon-reload systemctl restart docker
方案3:改用真正的DinD部署
如果需要新创建的容器完全运行在外层容器的环境内,可以不用挂载宿主机的docker.sock,直接使用官方docker:dind镜像作为Deployment的工作负载镜像,这样在内层创建的所有容器都会运行在DinD容器的网络命名空间内,直接复用外层的代理配置即可。
内容的提问来源于stack exchange,提问作者wsams

