使用本机代理在服务器上拉取Docker镜像
现在国内服务器拉取Docker Hub镜像越来越麻烦,直连经常超时,很多公共镜像源也不稳定。更尴尬的是,服务器上通常没有代理环境,为了偶尔拉一个镜像专门在服务器部署代理又有点重。
如果本地电脑已经有可用代理,就可以通过SSH远程端口映射,把本地代理端口临时映射到服务器上。服务器访问自己的127.0.0.1:7890,实际流量会通过SSH转发到本地电脑的代理端口。
前提条件
- 本地电脑可以正常使用代理,本文以HTTP代理
127.0.0.1:7890为例。 - 本地电脑可以SSH登录服务器。
- 服务器已经安装Docker。
- 如果使用方式二,服务器还需要安装
skopeo。
本文命令默认使用root用户执行,如果使用普通用户,请在服务器命令前加
sudo。
SSH远程端口映射
这一步在本地电脑执行,不是在服务器执行。
ssh -N -R 127.0.0.1:7890:127.0.0.1:7890 root@服务器IP这个命令里的-R是远程端口映射,参数顺序可以理解为:
ssh -R 服务器监听地址:服务器端口:本地代理地址:本地代理端口 用户@服务器对应到上面的命令:
- 第一个
127.0.0.1:7890是服务器上的监听地址和端口,也就是服务器里要使用的代理入口。 - 第二个
127.0.0.1:7890是本地电脑上的代理地址和端口,也就是本地真实可用的代理。 root@服务器IP是SSH登录的服务器账号和地址。-N表示只建立SSH连接和端口映射,不在服务器上执行命令。
默认绑定127.0.0.1,只允许服务器本机访问这个映射端口,不会把代理端口暴露到公网。
如果服务器的7890端口已经被占用,可以把服务器端口换成其他端口,例如:
ssh -N -R 127.0.0.1:17890:127.0.0.1:7890 root@服务器IP这时后续在服务器里使用的代理地址就改成:
http://127.0.0.1:17890测试代理是否可用
保持上面的SSH窗口不要关闭,然后在服务器执行:
curl -I -x http://127.0.0.1:7890 https://registry-1.docker.io/v2/如果返回401 Unauthorized也没问题,说明已经连到了Docker Registry,只是Docker Hub需要鉴权流程。这里主要看是否还会超时或者连接失败。
方式一:配置Docker代理拉取
Docker本身支持给daemon配置代理,配置后直接使用docker pull即可。
写入Docker代理配置
在服务器执行:
mkdir -p /etc/systemd/system/docker.service.d
tee /etc/systemd/system/docker.service.d/http-proxy.conf <<'EOF'
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890"
Environment="NO_PROXY=localhost,127.0.0.1,::1"
EOF如果前面SSH映射使用的是17890,这里也要改成:
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:17890"
Environment="HTTPS_PROXY=http://127.0.0.1:17890"
Environment="NO_PROXY=localhost,127.0.0.1,::1"重启Docker
systemctl daemon-reload
systemctl restart docker查看配置是否生效:
systemctl show --property=Environment docker然后正常拉取镜像:
docker pull docker.io/library/nginx:latest方式一的问题
这种方式简单直接,但是有几个明显缺点:
- 需要重启Docker服务,可能影响正在运行的容器。
- 配置是持久的,下次
docker pull仍然会默认走代理。 - 如果你平时还想使用镜像源或者直连拉取,就需要来回改配置和重启Docker,不太适合只想临时拉一个镜像的场景。
如果要恢复,可以删除这个配置并再次重启Docker:
rm -f /etc/systemd/system/docker.service.d/http-proxy.conf
systemctl daemon-reload
systemctl restart docker方式二:使用skopeo临时拉取
我更推荐这种方式。skopeo可以把远程仓库里的镜像复制到本机Docker daemon中,而且代理只对当前命令生效,不需要修改Docker配置,也不需要重启Docker。
安装skopeo
Debian / Ubuntu:
apt update && apt install -y skopeoRocky Linux / AlmaLinux / Fedora / RHEL 8+:
dnf install -y skopeoCentOS 7等使用yum的系统:
yum install -y skopeo如果旧系统的软件源里没有skopeo,可以先启用系统可用的软件源或EPEL,再重新安装:
yum install -y epel-release
yum install -y skopeo确认安装成功:
skopeo --version拉取镜像到Docker
在服务器执行:
HTTP_PROXY=http://127.0.0.1:7890 \
HTTPS_PROXY=http://127.0.0.1:7890 \
skopeo copy docker://docker.io/library/nginx:latest docker-daemon:nginx:latest这条命令的含义:
HTTP_PROXY和HTTPS_PROXY只对这一次skopeo copy生效。docker://docker.io/library/nginx:latest是远程镜像地址。docker-daemon:nginx:latest表示把镜像写入本机Docker daemon,镜像名为nginx:latest。
如果使用普通用户,并且访问Docker需要sudo权限,可以使用:
sudo env HTTP_PROXY=http://127.0.0.1:7890 HTTPS_PROXY=http://127.0.0.1:7890 \
skopeo copy docker://docker.io/library/nginx:latest docker-daemon:nginx:latest如果SSH映射使用的是17890端口,把代理地址替换为:
HTTP_PROXY=http://127.0.0.1:17890 \
HTTPS_PROXY=http://127.0.0.1:17890 \
skopeo copy docker://docker.io/library/nginx:latest docker-daemon:nginx:latest拉取完成后查看Docker镜像:
docker images nginx能看到nginx:latest就说明镜像已经进入Docker本地镜像列表,可以直接docker run或者在docker compose里使用。
两种方式怎么选
- 只是临时拉取一两个镜像:推荐方式二,使用
skopeo copy,不改Docker配置,也不重启服务。 - 服务器短时间内要大量拉取镜像:可以考虑方式一,配置Docker daemon代理后统一使用
docker pull。 - 服务器上已经有重要容器在跑:优先方式二,避免重启Docker带来的影响。
