本教程展示镜像标签排查、仓库入口检查,以及校验并导入镜像后使用本地镜像启动服务的步骤。实测演示为单台 Ubuntu 虚拟机分阶段对照。
实测范围与画面说明
本期使用 Ubuntu 26.04 amd64、Docker Engine 29.9.3 和 Compose v5.7.0。来源阶段和目标阶段使用同一台演示虚拟机的不同阶段与目录。
实测已验证两条结果:故意写错标签后,修正标签并重新拉取成功;本地缺少镜像时启动失败,校验并导入归档后,用 --pull never --no-build 启动,容器 Up,网页返回 HTTP 200。
E021 终端画面为真实测试日志的重排回放。DNS、持续网络超时和 Docker Hub 限流采用条件化排查示意。本次直接拉取成功,持续超时和限流未实测复现。
完整命令
下列代码按公开命令稿保留。按自己的服务名、镜像清单、目标平台和项目端口调整。
环境:Ubuntu 26.04 amd64,Docker Engine 29.9.3,Compose v5.7.0。以下练习使用单服务 Nginx,端口仅绑定在本机回环地址。
1. 分开拉镜像与启动服务
在你自己的 Compose 项目目录运行,替换 web 为实际服务名。
docker compose config --images docker compose --progress plain pull web
如果报错指向某个镜像引用且提示 not found,先核对仓库名和标签。比如本期故意将 nginx:stable-alpine 写成了 nginx:stable-alpnie。修正 Compose 的 image: 行后重复以上两条命令,看到 Pulled 再启动服务。私有镜像还要核对仓库授权和登录状态。
2. 在实际拉取的机器上检查连接
这里用 Docker Hub 的报错域名举例。自建或其他仓库使用对应域名及接口。
getent ahosts registry-1.docker.io
curl -sS --connect-timeout 5 --max-time 12 -o /dev/null \
-w 'HTTP %{http_code}\n' https://registry-1.docker.io/v2/
- 没有 DNS 结果或提示无法解析时,先检查这台目标机的 DNS。修复后先重复解析,再重试拉取。
- 连接反复超时时,检查这台目标机到报错域名的网络出口。浏览器访问其他站点成功,只能说明那次浏览器请求成功。
- 此 Docker Hub 入口的无凭据探测返回
HTTP 401,说明该次请求收到响应。继续实际执行docker compose --progress plain pull web,验证认证与镜像层也能完成。 - Docker Hub 返回
429时,按完整响应区分拉取额度和请求过多。具体处理见 Docker Hub 官方排障 ↗。
3. 来源机导出
先在 Ubuntu 目标机用 dpkg --print-architecture 查看架构。以下练习使用 linux/amd64,来源机必须能取得目标平台的镜像。真实项目使用 docker compose config --images 得到的镜像名与标签。
docker image pull --platform linux/amd64 nginx:stable-alpine
docker image inspect nginx:stable-alpine --format '{{.Os}}/{{.Architecture}} {{.Id}}'
docker image save -o nginx-stable-alpine.tar nginx:stable-alpine
sha256sum nginx-stable-alpine.tar > SHA256.txt
记录平台和镜像 ID。把归档和清单一起带到目标机。校验清单用于检测文件变化,文件和清单都应来自可信渠道。多服务项目准备每个服务实际引用的镜像。
4. 目标机导入并验证
先在放有归档和清单的目录运行。校验返回 OK 后才会导入。
sha256sum -c SHA256.txt && docker image load -i nginx-stable-alpine.tar
docker image inspect nginx:stable-alpine --format '{{.Os}}/{{.Architecture}} {{.Id}}'
确认标签、平台和 ID,回到 Compose 项目目录。练习使用配套 compose.yaml,或者保存以下配置。
services:
web:
image: nginx:stable-alpine
ports:
- "127.0.0.1:18221:80"
docker compose up -d --pull never --no-build docker compose ps curl --retry 5 --retry-connrefused --max-time 10 -fsSI http://127.0.0.1:18221
容器显示 Up,且本示例返回 HTTP/1.1 200 OK,才算服务跑通。自己的项目以实际映射端口和业务验收条件为准。只清理自己新建的演示项目时,可在其目录运行 docker compose down。
镜像归档包含镜像内容。Compose 文件、应用配置、卷、挂载文件和数据库数据需按项目单独准备。本期验证了禁止拉取和构建时使用本地镜像完成启动,运行期依赖外网的其他项目仍应另行验证。
官方参考
本期练习资料与文稿下载
练习归档是 nginx:stable-alpine 的 linux/amd64 实测快照,26,992,640 字节。先把四份练习文件下载到同一目录,保留文件名,再按 README 校验和操作。
- 下载完整命令 Markdown
- 下载完整公开视频文稿 Markdown
- 下载compose.yaml
- 下载练习 README.md
- 下载SHA256.txt 校验清单
- 下载nginx-stable-alpine.tar 镜像归档(约27 MB)
归档 SHA-256:6c125e0559ab58ab5be09f0250b06f4bc96e5c187891846fb6cfc8272c087001
按视频章节回看
完整视频文稿
展开完整口播文稿
镜像卡住时先做什么
上期装好了 Docker,启动网页时,镜像却卡在下载。你遇到这个画面,先把拉取单独跑一遍,看是哪一步失败。如果目标机确实拉不到,我会从准备镜像开始,演示怎么导入,再用本地镜像启动,直到网页返回 200。
单独拉取与修正镜像标签
先到 Compose 文件所在的目录。运行 docker compose config --images,确认项目实际要用的镜像。这个项目只有一个服务,叫 web。接着单独拉 web 的镜像。
屏幕上的 plain 会把进度按行留下来,失败时你就能回看最后几行。等拉取成功,再执行启动命令。这两步拆开,拉取报错就有了单独的输出。
这次错误指向一条具体的镜像引用,末尾说找不到。我故意把 alpine 末尾的字母拼错了。你可以对照镜像发布方列出的标签,把 Compose 文件里的 image 改成实际存在的版本。
我把它改回 stable-alpine,再看一次配置展开后的镜像名,重跑刚才的拉取。现在能看到每层下载和解包,最后显示 Pulled。这就确认了改对标签之后,镜像可以拉下来。
看报错区分连接、认证与限流
如果你看到的是超时,先看错误里写的是哪个域名。我在这台 Ubuntu 上用 curl 请求 Docker Hub 的 v2 入口,连接最多等 5 秒,整次请求最多等 12 秒。
这里没带登录凭据,收到 401,说明这一次请求拿到了仓库入口的响应。拉取还涉及认证和镜像层下载,所以接下来仍要重跑 Compose 的拉取命令。
如果 curl 提示域名无法解析,就先查目标机的 DNS。如果能解析,连接却反复超时,就拿报错中的域名检查目标机的网络出口,或者联系管理这台机器的人。遇到 429,先读完整提示,按对应的限流处理。
如果你眼下只想把服务跑起来,又有一台能拉到同一个镜像的机器,可以走下面这条离线路线。
导出、校验并导入本地镜像
先在目标机确认 CPU 架构。这台 Ubuntu 返回 amd64。准备镜像的机器也要有目标平台的版本。先拉项目实际使用的镜像,再用 image inspect 看平台和镜像 ID。
我这里是 linux/amd64,标签是 nginx:stable-alpine。
接着执行 docker image save,把这个标签保存成 tar 文件。再用 sha256sum 生成校验清单。把归档和清单一起传给目标机,比如用已有的文件传输方式,或者用 U 盘。
清单用来检查传过去的文件有没有变化。镜像的来源,还得由你选可信的发布方。
接下来看目标端。我用同一台演示虚拟机分两阶段做对照。这个阶段开始时,本地没有刚才那个标签。先试一次只用本地镜像启动,Docker 报找不到镜像。
进入放着归档和校验清单的目录,执行 sha256sum -c。看到归档显示 OK,再用 docker image load 导入。如果校验失败,重新传一份,校验通过后再继续。
导入完成会显示 Loaded image 和标签。用 image inspect 再查一次,确认目标端的镜像平台和 ID 与来源端一致,标签也与 Compose 里写的相同。
用本地镜像启动并验证 HTTP 200
回到 Compose 项目目录,执行屏幕上这条命令。pull never 让 Compose 只用本地已有的镜像,no-build 跳过构建。
再运行 docker compose ps,这次 web 是 Up。最后请求演示项目映射的本地端口,返回 HTTP 200,服务已经能响应。
换成自己的项目时,用配置展开后的镜像清单逐个准备,再按你的项目端口验证。数据库数据和挂载文件还要单独准备,镜像归档只解决镜像这一关。你可以先用这个单服务示例把整条路线走一遍,再用到自己的项目。
这里是西楚极客,我们继续用 AI,把真正能运行的项目做出来。下期见。
Ubuntu + Docker 自建
第1篇 · Ubuntu 26.04 安装 Docker 和 Docker Compose · 上期视频 ↗
第2篇 · 本期镜像拉取排障与离线启动 · 全部文章 →