阿里云 ACR 个人版打通镜像 push/pull 全流程(含踩坑记录)

背景

想把本地调好的容器推到远程仓库,换机器直接拉。第一反应是 Docker Hub,结果:

复制代码
Error response from daemon: Get "https://registry-1.docker.io/v2/": dial tcp 204.79.197.217:443: connect: no route to host

国内直连 Docker Hub 基本不可用。科学上网能解决 ,但 push 几十 GB 的镜像,好费流量。最终方案:阿里云 ACR 个人版,免费、国内直连、不需要科学上网。

一、开通 ACR 个人版

  1. 阿里云控制台搜索「容器镜像服务 ACR」,创建个人版实例,选一个地域(建议离自己近的)。
  2. 进入实例后做三件事:
    • 仓库管理 → 访问凭证:设置 Registry 登录密码(注意这不是阿里云账号密码,是 docker login 专用的独立密码)
    • 同页面查看登录用户名(主账号就是阿里云账号全名)
    • 命名空间 :创建一个命名空间,并打开「自动创建仓库」开关

新版个人实例的域名格式是:

复制代码
crpi-xxxxxxxx.cn-<地域>.personal.cr.aliyuncs.com

不再是老的 registry.cn-xxx.aliyuncs.com别手拼域名,直接从访问凭证页复制 ,我一开始用了裸的 registry.aliyuncs.com,直接报:

复制代码
unauthorized: authentication required

二、把容器保存为镜像

docker commit 把容器当前文件系统快照成镜像,原容器不受影响,运行中也能 commit(默认短暂 pause 保证一致性):

bash 复制代码
docker commit <容器名> myname/vllm:v1

两个要点:

  • commit 只保存文件系统,不包含挂载卷(-v)里的数据
  • run 参数也不会保存--gpus-p--shm-size 这些下次运行还得自己带,建议写个 start.sh 和镜像配套。
  • myname/vllm:v1 为后面命令的镜像id

三、打 tag 并推送

bash 复制代码
# 登录(域名、用户名从访问凭证页复制)
docker login --username=<登录名> crpi-xxxxxxxx.cn-<地域>.personal.cr.aliyuncs.com

# 打上完整仓库路径的 tag
docker tag myname/vllm:v1 crpi-xxxxxxxx.cn-<地域>.personal.cr.aliyuncs.com/<命名空间>/vllm:v1

# 推送
docker push crpi-xxxxxxxx.cn-<地域>.personal.cr.aliyuncs.com/<命名空间>/vllm:v1

踩坑:denied: requested access to the resource is denied

push 时所有层 Preparing/Waiting 完直接 denied。排查下来是三件事没对齐,缺一不可:

  1. 必须 login 到 crpi 这个确切域名 。Docker 凭证按 registry 域名分开存,登录过 Docker Hub 不等于登录了 ACR。可以 cat ~/.docker/config.json 确认 auths 里有 crpi 域名。
  2. 命名空间必须已在控制台创建,且和 tag 里写的完全一致。
  3. 仓库要么手动建好,要么命名空间开了「自动创建仓库」,否则 push 一个不存在的仓库会被拒。

四、在另一台机器拉取

bash 复制代码
# 私有仓库需要先登录
docker login --username=<登录名> crpi-xxxxxxxx.cn-<地域>.personal.cr.aliyuncs.com

docker pull crpi-xxxxxxxx.cn-<地域>.personal.cr.aliyuncs.com/<命名空间>/vllm:v1

# 镜像名太长,打个短 tag
docker tag crpi-xxxxxxxx.cn-<地域>.personal.cr.aliyuncs.com/<命名空间>/vllm:v1 vllm:v1

踩坑:Cannot connect to the Docker daemon

新机器上 pull 时报:

复制代码
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

systemctl status docker 发现 dockerd 起不来,最后定位到 /etc/docker/daemon.jsonJSON 语法错误 ------registry-mirrors 数组结束后忘了加逗号就接了 runtimes 字段。一个逗号让整个 Docker 服务瘫痪。

验证 JSON 语法的土办法:

bash 复制代码
cat /etc/docker/daemon.json | python3 -m json.tool

能格式化输出就没问题,报错就是语法有问题。

另外两个相关认知:

  • registry-mirrors 只加速 docker.io 的拉取,拉 crpi 域名是直连阿里云,和加速器无关。网上抄来的第三方加速器很多已失效,失效条目还会拖慢重试,建议精简。
  • 普通用户报 daemon 连不上,也可能是不在 docker 组:sudo usermod -aG docker $USER 后重新登录。
环节 关键点
开通 个人版免费,一个账号限一个实例,域名从访问凭证页复制
commit 不含挂载卷数据和 run 参数,原容器无影响
push login 域名、命名空间、自动创建仓库三者对齐
pull 私有仓库先 login;daemon.json 语法错误会让 Docker 整个起不来

如果只是自己两台机器间倒腾、不需要公网分发,docker save | gzip 导出 tar 再 scp 过去反而更快,不受仓库限速和配额约束。ACR 的价值在于长期托管和多机分发。