
某天需要在云服务器上部署Redis Stack,心想拉个镜像应该很快的。
结果一执行:
docker pull redis/redis-stack-server:6.2.6就开始了漫长的等待......
卡......卡......卡......
等了半天都没动静,最后直接超时了。
我测试了一下网络环境:
# ping Google
ping google.com
# 超时,ping不通
# curl测试外网
curl https://www.google.com
# 连接超时
# 试试国内网站
curl https://www.baidu.com
# 正常果然,这是国内服务器的老问题:外网访问受限。
难怪Docker拉镜像拉不下来,连Google都ping不通,访问Docker Hub当然也不稳定。
Docker给的错误信息是:
✘ redis Error Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers... 85.2s这下明白了:国内服务器访问Docker Hub就是不稳定,经常超时。
我本地电脑是有科学上网工具的,代理很稳定。突然想到:能不能让远程服务器通过我本地的代理上网?
搜了一下,发现SSH有个很强大的功能:反向代理通道。
简单来说就是:
在我本地电脑上执行:
ssh -N -R 1081:127.0.0.1:7890 root@115.120.221.105这个命令的意思:
-N:不执行命令,只建立通道-R 1081:127.0.0.1:7890:把我本地的7890端口映射到服务器的1081端口root@115.120.221.105:目标服务器在服务器上测试:
curl -x socks5h://127.0.0.1:1081 https://api.ipify.org如果能返回IP地址,说明代理通道建立成功了。
光有代理通道还不够,还得让Docker知道要用这个代理。
Docker daemon默认不会使用shell的代理环境变量,需要单独配置:
# 创建配置目录
sudo mkdir -p /etc/systemd/system/docker.service.d
# 创建代理配置文件
sudo vim /etc/systemd/system/docker.service.d/http-proxy.conf配置内容:
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:1081"
Environment="HTTPS_PROXY=http://127.0.0.1:1081"
Environment="NO_PROXY=localhost,127.0.0.1"sudo systemctl daemon-reload
sudo systemctl restart dockersudo systemctl show --property=Environment docker如果能看到代理配置,说明设置成功了。
配置完成后,再次尝试拉取镜像:
docker pull redis/redis-stack-server:6.2.6这次很顺利就拉下来了!通过本地代理,网络稳定多了。

可以看到,现在能正常访问Google等外网了,Docker拉镜像也没问题。
用完代理后,记得要清理配置!
如果你断开了SSH连接,或者本地代理关了,但是Docker的代理配置还在,就会出现这种情况:

Docker会一直尝试连接已经不存在的代理地址,导致拉镜像失败。
# 删除代理配置文件
sudo rm /etc/systemd/system/docker.service.d/http-proxy.conf
# 重新加载配置
sudo systemctl daemon-reload
sudo systemctl restart docker为了方便使用,我写了两个脚本来自动开启和关闭Docker代理:
#!/bin/bash
# enable-docker-proxy.sh
echo "正在配置Docker代理..."
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:1081"
Environment="HTTPS_PROXY=http://127.0.0.1:1081"
Environment="NO_PROXY=localhost,127.0.0.1"
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
echo "Docker代理配置完成!"#!/bin/bash
# disable-docker-proxy.sh
echo "正在移除Docker代理配置..."
sudo rm -f /etc/systemd/system/docker.service.d/http-proxy.conf
sudo systemctl daemon-reload
sudo systemctl restart docker
echo "Docker代理配置已移除!"比起各种VPN或者其他代理方案,SSH代理通道是最稳定的。只要SSH能连上,代理就能用。
用完一定要记得清理Docker的代理配置,否则下次不开代理的时候会各种连不上。
使用期间,本地的代理软件不能关,SSH连接也不能断。可以用screen或者tmux来保持连接。
这种方法比较适合临时拉镜像用,不适合长期运行。如果需要长期使用,建议在服务器上直接配置代理。
选择远程端口的时候,要避免和服务器上已有的服务冲突。我用1081这个端口一般比较安全。
有些代理软件提供的是socks5协议,有些是http协议。Docker daemon一般用http代理,要注意协议转换。
如果代理通道建立失败,检查一下本地和远程的防火墙设置,确保端口没有被阻挡。
这个SSH代理通道的方法虽然看起来有点复杂,但是非常实用。特别是在网络环境不好的情况下,能够稳定地拉取Docker镜像。
关键是要理解原理:通过SSH把本地的网络能力"借给"远程服务器用。
现在我每次遇到远程服务器网络问题,第一个想到的就是这个方法。简单、稳定、有效!
提醒:使用这个方法的时候,记得用完要清理Docker的代理配置,否则下次不开代理就会连不上了!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。