
前言
学习镜像的导入与导出主要有两个原因:
- 将自己搭建好的镜像移植到别的机器。
- 机器处于无网络环境,无法从网上下载镜像。
在Docker中,实现镜像导出与导入主要涉及 export\import
、save\load
这两组命令 (这两组命令千万千万不要混用)
docker export
与 docker import
docker export
docker export
命令用于将一个运行中的容器导出为一个 tar
归档文件。这个归档文件包含了容器在导出时的文件系统快照,但不包含镜像的历史信息和元数据。
语法格式:
|
|
先查看当前的容器情况:
|
|
例如,我们有一个正在运行的容器 my_container
,想要将其导出为 my_container_export.tar
文件,可以执行以下命令:
|
|
docker import
docker import
命令用于从一个 tar
归档文件创建一个新的镜像。这个命令会将 export
导出的文件系统快照重新构建为一个镜像。
语法格式:
|
|
例如,我们将刚才导出的 my_container_export.tar
文件导入为一个新的镜像 my_new_image:v1
:
|
|
注意事项
- 镜像历史信息:由于
export
导出的文件不包含镜像历史信息,所以使用import
导入后生成的镜像层数会变为一层,这可能会影响镜像的可维护性和大小。例如,如果原镜像有多个构建步骤,经过export
和import
后,这些步骤将不可追溯。 - 容器状态:
export
操作基于容器当前的状态,因此在导出前确保容器内的应用和数据是你期望的状态。如果容器内有正在运行的进程,导出时这些进程可能会被冻结,以保证数据一致性。
docker save
与 docker load
docker save
docker save
命令用于将一个或多个镜像保存为一个 tar
归档文件。与 export
不同,save
会保留镜像的所有历史信息和元数据。
语法格式:
|
|
例如,要保存 ubuntu:latest
镜像为 ubuntu_save.tar
文件:
|
|
如果要保存多个镜像,可以在命令后依次列出镜像名:
|
|
docker load
docker load
命令用于从 save
生成的 tar
归档文件中加载镜像。
语法格式:
|
|
例如,加载刚才保存的 ubuntu_save.tar
文件:
|
|
注意事项
- 镜像大小:由于
save
保留了镜像的历史信息,生成的归档文件通常会比export
生成的文件大,因为它包含了更多的元数据和镜像构建历史。 - 网络环境:在无网络环境下,
save
和load
是在不同机器间迁移镜像的有效方式。但要注意目标机器上的Docker版本是否与源机器兼容,以确保镜像能够正确加载。
export/import
与 save/load
的对比
直接区别
-
export
:从容器中生成tar文件,不支持将多个镜像打包到一个文件 -
save
:从镜像中生成tar文件,支持将多个镜像打包到一个文件 -
import
:可以为镜像指定新名称 -
load
:不能对载入的镜像重命名
使用场景
export/import
:适用于对镜像历史信息不关心,只需要容器当前文件系统状态的场景,比如快速迁移一个运行中的容器状态到其他机器。例如,在开发测试环境中,快速复制一个已配置好的容器环境。save/load
:更适合需要完整保留镜像构建历史和元数据的场景,比如在生产环境中迁移镜像,确保镜像的完整性和可追溯性,或者是要部署的客户服务器并不能连外网,用自己的可联网的电脑下载镜像,然后导出。
镜像特性
- 镜像层数:
export/import
会使镜像层数变为一层,而save/load
保留原镜像的层数结构。 - 镜像大小:一般情况下,
save
生成的归档文件大于export
生成的文件,因为save
包含更多信息。
问题
invalid tar header
在使用load
导入镜像时出错:archive/tar: invalid tar header
-
问题环境:我的镜像是从win11下的wsldocker
save
的,而要load
的机器为ubuntu22.04server -
问题原因:我打开运行
save
命令时,使用的是win11的powershell,而powershell有个问题,Powershell 向 标准输出STDOUT 发出两个字节字符,而不是一个字节字符。如果你查看该文件,你会注意到 TAR 头文件在应该是正确的头文件之间(和文件的其余部分)之间有 null。这解释了为什么文件大小是原来的两倍。比如我要save
Mysql的镜像,原本只有500M,但是save
之后却1000MB。当你把tar文件传过去load
,就会出现这个问题。 -
解决方法:
- 不使用powershell,而去使用CMD(命令提示符),这样不会出现上述问题。CMD 不会向 STDOUT 发出多字节字符。如果在 Windows 上使用 CMD,保存文件的 STDOUT 方法在不同的作系统上都能正常工作。
- 替换
>
和<
来导出和导入镜像,docker save
的-o选项和docker load
的-i 选项选项可以直接指定输入和输出文件,避免使用标准输入输出流,从而绕过 PowerShell 的字符编码问题.1 2 3 4
# 导出镜像 docker save [image] -o file.tar # 导入镜像 docker load [image] -i file.tar
-
参考