docker 镜像找不到:manifest unknown / not found 速查
更新时间:2026-10-24。FAQ 速查页,面向刚用 docker 拉镜像就撞
manifest unknown或not found的同学。这类报错的字面意思是:仓库里(或本地)没有一个叫「名字:tag」的镜像清单(manifest,记录镜像层与配置的那份元数据)。但「没有这份清单」背后的原因收敛在六根轴上:tag 打错、镜像名拼错、镜像根本没推上去、私有仓库没登录、平台架构不匹配、镜像被仓库清理或换了地址。顺一遍基本必中。如果报错换成Error response from daemon: ... denied(权限被拒而不是清单不存在),请转 docker 权限被拒速查。
本文要回答的问题
manifest for xxx:yyy not found: manifest unknown: manifest unknown和pull access denied差在哪?- 为什么
docker run nginx:latset这种错 docker 自己不会提示拼写问题? - 私有仓库的镜像名写全了吗?缺了 registry 前缀会怎样?
no matching manifest for linux/arm64/v8是什么意思,镜像明明在仓库里?- 本地
docker images里的镜像为什么 push 完别人还是拉不到?
一、报错原文与典型现象
报错集中在 pull 与 run(run 会先隐式 pull)两个动作上,几个变体要分清(工程路径以 /proj/demo 占位):
$ docker pull myapp:latset
Error response from daemon: manifest for myapp:latset not found: manifest unknown: manifest unknown$ docker pull registry.example.com/team/myapp:v1.2
Error response from daemon: pull access denied for registry.example.com/team/myapp, repository does not exist or may require 'docker login'$ docker pull myapp:latest
no matching manifest for linux/arm64/v8 in the manifest list entries$ docker run --rm myapp:latest
Unable to find image 'myapp:latest' locally
docker: Error response from daemon: pull access denied for myapp ...读报错先抓三个信号:报 manifest unknown 是名字或 tag 不存在——仓库在、能访问,只是没这一份清单;报 pull access denied 是仓库这层就拒了——没登录或仓库名不对;报 no matching manifest for linux/arm64 是清单在但没你的架构——镜像在,只是没有 arm64(或 amd64)那一份变体。三个分支走的排查路线完全不同。
二、病因处置速查表
| 报错现象 / 场景 | 可能原因 | 快速验证 | 处置 |
|---|---|---|---|
| manifest unknown | tag 拼错(latset 少个 e) | 仓库页面或 docker buildx imagetools inspect 名字 列实际 tag | 用真实存在的 tag 重拉 |
| manifest unknown | 忘了 tag,默认 latest 但仓库没推 latest | 同上,看 tag 列表里有没有 latest | 拉指定版本 tag,或补推 latest |
| pull access denied / not found | 镜像名拼错或少了 registry 前缀 | 核对完整名:registry/命名空间/仓库名 | 写全限定名重拉 |
| pull access denied,提示 require login | 私有仓库未登录或凭据过期 | docker login registry.example.com 看是否成功 | 登录后重拉;CI 里同样补 login |
| no matching manifest for linux/xxx | 镜像没构建当前平台架构 | inspect 输出里没有对应 os/arch 条目 | 用 --platform 指定存在的架构,或构建多架构镜像 |
| 昨天还能拉,今天 manifest unknown | 仓库端 tag 被覆盖、删除或镜像过期清理 | 对比 tag 列表与历史 CI 记录 | 锁定到内容摘要(digest)或找维护者恢复 |
| 本地能 run,同事拉不到 | 镜像只在本地 build 没 push | 本地 docker images 有、仓库页面没有 | docker push 推上去再发 |
| build 时报 base image not found | Dockerfile FROM 的基础镜像名/tag 错 | 单独 docker pull 那一行 FROM | 修正 FROM 行 |
三、排查决策图
下面这张图是标准排查路线,颜色按角色区分:红是报错入口与命中的根因,蓝是排查动作,绿是通过分支,橙是修复动作,紫是防复发沉淀。
读这张图抓住一个分水岭:先把报错分成 manifest unknown 与 pull access denied 两档。前者仓库可达,问题在名字、tag、架构这三样「清单内容」;后者连仓库门都没进去,先查名字前缀和登录态。no matching manifest 是 manifest unknown 的特殊形态——清单在,但没你这颗 CPU 架构的那一份。
四、逐条排查展开
第一步:让仓库自己说它有什么。 不要去猜 tag,用一条命令列出远端真实存在的 tag 与架构清单:
docker buildx imagetools inspect registry.example.com/team/myapp
# 会列出 Name / MediaType / 各平台的 os、architecture 与 digest老版本没有 buildx 时,用 docker manifest inspect 名字:tag 或直接看仓库网页。拉取前核对一遍,「拼写幻觉」当场现形——latset、v1.2 写成 1.2、把命名空间 team 漏掉,都是这一层的常客。
tag 打错与 latest 缺席。 docker 对不存在的 tag 不会给「你是不是想写 latest」的提示,只回一句干巴巴的 manifest unknown。注意一个坑:不写 tag 时默认 latest,但很多团队的流水线只推版本号 tag(v1.2.3),从没推过 latest——这时 docker pull myapp 必炸而 docker pull myapp:v1.2.3 正常。修法二选一:拉的时候写全版本 tag;或者流水线补一步把最新版再打 latest 推上去。
镜像名要写全限定。 docker 对不带 registry 前缀的名字默认去 Docker Hub 找,myapp:v1.2 实际是 docker.io/library/myapp:v1.2。私有镜像必须写全 registry.example.com/team/myapp:v1.2 三段;少一段,轻则 404,重则拉到 Hub 上同名的陌生镜像(供应链层面是真风险,不只是报错问题)。Dockerfile 的 FROM、compose 的 image:、k8s 的 image: 同口径。
pull access denied 多半是登录态。 私有仓库就算仓库存在,未登录也回这条(它故意不区分「不存在」和「没权限」,防探测)。处置:
docker login registry.example.com
# 输入用户名与访问令牌(不是控制台密码,多数仓库要 PAT)
cat ~/.docker/config.json # 确认 auths 里有这个 registryCI/CD 里同样要 login——流水线每次起干净环境,凭据不落地就会挂在这一步;用流水线的密钥变量注入 docker login 即可。注意令牌过期是「上周还能拉」的常见根因。
架构不匹配:ARM 时代的专属坑。 在 Apple Silicon 或 ARM 服务器上拉只构建了 linux/amd64 的镜像,就报 no matching manifest for linux/arm64/v8。两条出路:临时用 --platform linux/amd64 强制跑(走模拟,慢一些但能用);正路是构建侧用 buildx 出多架构镜像:
docker buildx build --platform linux/amd64,linux/arm64 -t registry.example.com/team/myapp:v1.2 --push /proj/demo镜像没推送:本地有不等于仓库有。 docker build 只落在本地镜像库,同事和服务器那边当然 manifest unknown。养成习惯:docker images 里看到的镜像,交付前必须 docker push 到约定仓库,并以仓库页面能搜到为准。另外注意 push 的名字与 pull 的名字要完全一致——build 时打的 tag 是什么就推什么、拉什么。
tag 被覆盖与清理。 可变 tag(尤其是 latest、dev)会被新构建覆盖,仓库的保留策略还可能自动清理老 tag。「上周的 v1.2 今天没了」就按 digest 找回:digest 是内容哈希,tag 没了它还在(只要没被垃圾回收)。重要环境直接锁 digest 部署:myapp@sha256:...,完全免疫 tag 漂移。
离线仓库与代理环境。 公司内网常配了镜像代理或私有 mirror,这时「镜像找不到」还可能是代理把请求转去了不存在的上游路径。确认方法:对比 docker info 输出里的 Registry Mirrors 与实际拉取报错里的仓库地址是否一致;在纯外网机器上拉同一个名字能成功、内网必炸的,查代理配置而不是镜像本身。ctr、nerdctl 等其他运行时同理,但它们读的是各自的配置文件,别把 docker 的 daemon.json 当成全局生效,各运行时各自为政。
五、规范做法与预防
- 名字全限定:文档、脚本、compose、CI 里的镜像名一律
registry/命名空间/仓库:tag,不写裸名。 - 生产锁 digest:测试用 tag 图方便,生产部署清单里写
名字@sha256:摘要,杜绝 tag 被覆盖引发的「悄悄换版本」。 - 流水线即规范:构建-打 tag-推送进 CI 流水线,本地手 build 的镜像不进交付链路。
- 多架构默认开:buildx 构建默认带
linux/amd64,linux/arm64,团队里有 ARM 机器就不用临时救火。 - 凭据集中管:registry 访问令牌放 CI 密钥库与密码管理器,过期前轮换;个人机器
docker login一次写进 config.json。 - 拉前 inspect:脚本里
docker buildx imagetools inspect通过再 pull,失败直接给出本页链接。
这一篇在知识体系里的位置
本篇是 docker 排错速查簇的入口篇,定位「镜像这份清单不存在或够不着」:名字/tag/架构与推送问题看本篇;守护进程 socket、docker 组与挂载卷的权限类报错看 docker 权限被拒速查;镜像拉下来跑起来之后端口连不上的看 docker 容器端口连接被拒速查。buildx imagetools inspect、docker login、digest 锁定三件套路在一切镜像获取类报错里通用。
一句话总结
docker 镜像找不到先按报错原文分档:manifest unknown 是名字、tag 或架构层的问题——用 docker buildx imagetools inspect 列真实 tag 清单核对拼写、确认仓库推过 latest、ARM 机器核对有没有对应架构变体(没有就 --platform 或 buildx 出多架构);pull access denied 是仓库入口层的问题——名字写全 registry 前缀、私有仓库先 docker login、CI 里补凭据。本地能跑不等于仓库有,docker push 后交付才算数;重要部署锁 digest,tag 漂移与覆盖从此免疫。