docker pull 报 pull access denied 怎么解决?镜像拉取被拒的 5 种原因
现象:拉镜像被拒
pull access denied for myapp/api, repository does not exist or may
require 'docker login': denied: requested access to the resource is denied
一行结论:Docker Hub(或你用的 registry)拒绝匿名拉取这个镜像。拒绝的原因只有两类:要么「这个仓库根本不存在」,要么「存在但你没权限」。报错故意含糊(安全考虑,不区分两者),排查就是逐一排除。
五种原因,按概率排序
1. 镜像名拼错了(最常见)
Docker 镜像名的解析规则先搞清楚:
nginx → docker.io/library/nginx(官方镜像)
bitnami/nginx → docker.io/bitnami/nginx(用户/组织镜像)
registry.example.com/app → 私有 registry 上的镜像
两个高频错误:把个人镜像当官方镜像拉(docker pull myapp 找的是 library/myapp,不存在);或者多打/少打一段名字。先去 Docker Hub 页面确认镜像的完整路径和拼写。
2. tag 不存在
manifest for myapp/api:v1.2 not found 是近亲错误——仓库存在但 tag 写错了。特别是假设镜像有 latest tag 是经典陷阱:官方镜像基本都有 latest,个人镜像经常只 push 过具体版本号。去 Hub 页面的 Tags 列表核对,别凭感觉写。
3. 私有仓库没登录(或登错账号)
docker login # 默认 Docker Hub
docker login registry.example.com # 私有/自建 registry
cat ~/.docker/config.json # 看登录了哪些 registry、哪个账号
常见坑:登录了公司账号去拉个人仓库(反之亦然);CI 上的凭据过期;docker login 之后换了 context。重新 login 对应 registry 即可。
4. Docker Hub 限流(报错形态不同但要一起排查)
匿名拉取限 100 次/6 小时(按 IP)。超限的报错是 toomanyrequests: You have reached your pull rate limit——和 access denied 是两回事,但经常被混为一谈。免费账号登录后限额 200 次,基本够用。
5. 国内网络:配镜像加速器
国内直连 Docker Hub 经常超时或被重置,报错形态五花八门(timeout、EOF、unexpected status)。配加速器是标准解法,/etc/docker/daemon.json:
{
"registry-mirrors": ["https://docker.m.daocloud.io"]
}
改完 sudo systemctl restart docker。注意 daemon.json 不能有尾逗号,改坏了 daemon 起不来——排查方法见:Cannot connect to the Docker daemon 排查。
排查路线(一分钟定位)
# 1. 完整报错是什么?(access denied / not found / rate limit 三者方向完全不同)
docker pull myapp/api:v1.2
# 2. 登录状态
docker login
# 3. 换个官方镜像试试——官方能拉说明是权限/名字问题,官方也拉不动说明是网络
docker pull hello-world
# 4. 网络问题时验证加速器是否生效
docker info | grep -A3 "Registry Mirrors"
第 3 步是分水岭:hello-world 都拉不动 → 网络/限流(原因 4/5);只有你的镜像拉不动 → 名字/权限(原因 1/2/3)。
和相邻错误的分界
| 报错 | 含义 | 参考 |
|---|---|---|
| pull access denied | 仓库不存在或无权限 | 本篇 |
| manifest ... not found | 仓库存在,tag 不对 | manifest unknown 排查 |
| toomanyrequests | 拉取频率超限 | 登录或等待 |
| i/o timeout / EOF | 网络不通 | 配加速器(本篇原因 5) |
四个凭证源的冲突
Docker 拉取从四处取凭证:docker login 每注册表的凭证(~/.docker/config.json)、凭证助手(osxkeychain/wincred 按注册表配)、K8s 的 imagePullSecrets(命名空间作用域——CI pod 在错命名空间看不到凭证)、实例角色(ECR 的 IAM、GCP 的 SA——按 URL 解析的环境凭证)。冲突形态:陈旧的 docker login 覆盖了能用的实例角色(从 config.json 删那条)、换工作站后的助手不匹配、节点上挂了角色又配了冲突的 secret。auth 失败时的诊断序:用 CI 同机同用户 docker pull——一条命令把凭证源与管线配置分开。
三大 registry 各自的「有效凭证仍被拒」
ECR:token 每 12 小时过期(CI 里要刷新 login)、URL 的 region 前缀是必须的(漏了 = 凭证有效仍被拒的经典)。GHCR:用户名大小写敏感(token 对、仓库路径大小写错 = 拒绝)、PAT 即使拉公共镜像也要 read:packages。自建 Harbor:项目名是路径的一部分且大小写敏感、匿名拉取取决于项目公开性——配置错的项目除了登录全部拒绝。每个 registry 都有一个主导的「被拒真因」——知道你的那个,省一下午。
排查清单
- 镜像完整路径核对:官方无前缀、个人带用户名、私库带域名
- tag 存在吗?Hub 页面 Tags 列表核对,别假设有 latest
docker login对应 registry 了吗?~/.docker/config.json看记录- 报错是 access denied 还是 rate limit?后者是登录/等待问题
docker pull hello-world分水岭测试:判断是网络还是权限- 国内环境配 registry-mirrors 加速器
排查注记
五种原因虽按概率排序,但真正的结构在于报错故意含糊——安全考虑不区分「仓库不存在」和「无权限」,所以排查只能是逐一排除。排查路线第 3 步用 hello-world 做分水岭是设计过的:官方镜像都拉不动说明是网络/限流(原因 4/5),只有你的镜像拉不动才是名字/权限(原因 1/2/3)。限流那条单独并入清单,是因为 toomanyrequests 和 access denied 报错形态不同、却经常被混为一谈。
本文由 ToolVault 工具匣 提供。相关工具:Dockerfile 生成器、docker run 转 compose、Linux 命令速查。相关阅读:manifest unknown 排查、Docker daemon 连不上、npm 换源指南(同类网络问题)。访问 首页 查看更多开发者工具。
相关工具
相关文章
Linux crontab 定时任务实战:命令、日志与排查
crontab 不只是写表达式:三个必会命令、/etc/cron.d 与用户 crontab 的区别、任务没跑的五步排查法、PATH/时区/% 转义、MAILTO,以及秒级任务的正确解法。
docker run 转 docker-compose 完全指南:为什么转、怎么转、参数对照表
把 docker run 命令迁移到 docker-compose.yml 的完整指南:compose 相比裸 run 的五大优势、参数逐项对照表(端口/卷/环境变量/重启策略/网络)、常见坑(裸 -e 透传、匿名卷、--rm 语义),附在线转换器用法。
Permission denied (publickey) 怎么解决?Git 推送失败的 6 种原因与修复
git clone/push 报 Permission denied (publickey) fatal: Could not read from remote repository?覆盖公钥没生成、没加载进 agent、没添加到 GitHub/Gitee、多账号配错密钥、deploy key 权限、remote URL 写错六种根因,附 ssh -v 诊断方法。