Docker生存镜像到当地并载入当地镜像文件

[复制链接]
发表于 2026-10-3 15:31:11 来自手机 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×

Docker 镜像导出为本地文件与离线导入的完整做法

平时拉镜像靠配国内镜像源加速就够了,但有两类场景绕不开"导出再拷过去":一是目标机器完全不能上网,只能从能联网的机器下好镜像、拷到离线机器;二是镜像只存在于私有仓库或内网 registry,外部根本拉不到。这两种情况都用 docker save 导出、docker load 导入就能解决。

一、把镜像保存为本地文件

1. 先看现有镜像

docker images

列出当前机器上已有的全部镜像,记下名字和 tag。

2. 导出为 tar 文件

两个要点要先记住:

  • 产物必须是 tar 类型文件。
  • 导出指令里如果用的是镜像 ID,导出的 tar 恢复后 REPOSITORY 和 TAG 会显示为 none,需要再用镜像 ID 重新打标签;如果用的是镜像名则没有这个问题。

导出方式一,用 -o 指定输出文件:

# 导出到 /data/docker/nginx_latest.tar,文件名必须是 tar 类型,可以带路径
docker save -o /data/docker/nginx_latest.tar nginx

其中 nginx 是要导出的镜像(名称或 ID 均可,名称后面可以跟 TAG 指定版本)。

导出方式二,用重定向:

docker save nginx > nginx_latest01.tar

两种方式效果一样,都会在本地生成 nginx_latest.tar 和 nginx_latest01.tar。实际生产更推荐 -o,路径和文件名一目了然,重定向时如果忘了写重定向符号会直接把内容刷到终端里。

走镜像 ID 导出,用来验证上面那条注意点:

docker save -o nginx_latest_byID.tar 89da1fb6dcb9

这个 tar 用 docker load 导回来时就会出现 REPOSITORY/TAG = none,需要手动 docker tag 补标签。

二、把本地文件载入 Docker

把导好的 tar 复制到目标机器(scp、U 盘、内网传输都行),然后导入:

方式一,标准输入:

docker load < nginx_latest.tar

方式二,指定输入文件:

docker load --input nginx_latest.tar

第二种写法本质上和第一种一样。用方式一时可以配合管道,一边 cat 一边导,适合单文件传输的场景。

再强调一次 ID 导出的问题:如果把 nginx_latest_byID.tar 导进来,docker images 里看到的是 <none> 一行。补标签:

docker tag 89da1fb6dcb9 nginx:latest

补完就能正常 run 了。

三、批量导出与批量导入脚本

3.1 批量导出脚本 save_images.sh

#!/bin/bash

# 取出 "image:tag" 格式的镜像全名
IMG_NAME=`docker images | grep -v TAG | awk '{print $1":"$2}'`

# 镜像名里含 "/" 的转成 "_",避免做文件名
echo $IMG_NAME | awk '{gsub(/\//,"\n",$0)}{print $0}'

# 定义镜像存放目录
DIR="/data/docker/image_save"
if [ ! -d "$DIR" ]; then
  echo -e "\033[34m${DIR}\033[0m 不存在"
  mkdir -p "$DIR"
  echo -e "\033[34m${DIR}\033[0m 已创建"
else
  echo -e "\033[34m${DIR}\033[0m 已存在"
fi
echo ""

for IMAGE in $IMG_NAME
do
  echo -e "正在保存 \033[33m${IMAGE}\033[0m"
  SAVE_NAME=`echo $IMAGE | awk -F: '{print $1"_"$2}' | sed 's/\//_/g'`
  docker save $IMAGE -o ${DIR}/${SAVE_NAME}.tar
  echo -e "已保存到 \033[34m${DIR}/\033[31m${SAVE_NAME}.tar\033[0m"
  echo ""
done

脚本要点:grep -v TAG 是为了去掉 docker images 表头那行 REPOSITORY TAG ...;gsub 把仓库名里的斜杠换成下划线,否则私有仓库的 registry:5000/team/app 直接拿来当文件名会出问题;最后用 -F: 把 name 和 tag 拼成保存文件名。

保存后给执行权限(演示环境图省事直接 777,生产建议按最小权限给):

chmod 777 save_images.sh

3.2 批量导入脚本 load_images.sh

#!/bin/bash

# 这里填镜像文件的存放目录
IMAGE_DIR="/data/docker/image_save"

for IMAGE in `ls $IMAGE_DIR`
do
  echo -e "正在导入镜像 \033[33m$IMAGE\033[0m"
  docker load -i ${IMAGE_DIR}/${IMAGE}
  echo -e "已成功导入镜像 \033[33m$IMAGE\033[0m"
  echo ""
done

四、容易出现的问题

  • 导出后 docker images 找不到:先看 docker load 的输出,是否报镜像已存在而跳过;确认文件完整(tar tf xxx.tar 能列出层目录)。
  • 导入后 tag 是 none:导出时用了镜像 ID,补一条 docker tag <id> 名字:版本。
  • 磁盘空间不够:多镜像同时导出很容易撑爆 /var/lib/docker,先 df -h 看一眼,导完用 docker image prune 清理无用层。
  • 跨架构拷过去跑不了:在 arm 机器上导出的 tar 拷到 amd64 机器上,镜像能导入但容器启动会报 exec format error,导出前确认架构一致。
  • 离线机内核模块缺失:镜像能导入但依赖的内核模块目标机没有,这类问题 save/load 解决不了,得换镜像或补驱动。

小结

离线环境分发镜像的核心操作就两条:docker save -o 文件.tar 镜像名 导出,docker load -i 文件.tar 导入。批量场景用上面两个脚本,一个遍历 docker images 全量导出到指定目录,一个遍历目录全量导入。唯一要留心的坑是镜像 ID 导出会导致 REPOSITORY/TAG 变成 none,要么导出时用镜像名,要么导入后补一条 docker tag。

qidao123.com企服评测-应用市场 编辑提示

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表