## 4.6 其它制作镜像的方式 除了标准的使用 `Dockerfile` 生成镜像的方法外,由于各种特殊需求和历史原因,还提供了一些其它方法用以生成镜像。 ### 4.6.1 从 rootfs 压缩包导入 格式:`docker import [选项] <文件>||- [<仓库名>[:<标签>]]` 压缩包可以是本地文件、远程 Web 文件,甚至是从标准输入中得到。压缩包将会在镜像 `/` 目录展开,并直接作为镜像的文件系统内容导入。若还需要补充 `CMD`、`ENV` 等元数据,可以通过 `--change` 追加;但它不支持 `RUN`、`COPY` 这类依赖构建上下文或会生成新文件系统层的 Dockerfile 指令。 例如在 Debian/Ubuntu 主机上,可以先用 `debootstrap` 生成 Ubuntu 24.04(`noble`)的 rootfs,再通过标准输入导入为基础镜像: > **版本提示**:示例中的 Ubuntu 16.04 (Xenial) 已于 2021 年 4 月停止支持。如果用于生产环境,建议更新至 Ubuntu 22.04 LTS 或更新版本。 ```bash $ sudo debootstrap noble noble > /dev/null $ sudo tar -C noble -c . | docker import - ubuntu:noble sha256:81ec9a55a92a5618161f68ae691d092bf14d700129093158297b3d01593f4ee3 ``` 这组命令会先得到 `noble/` 目录下的 rootfs,再把它打包后导入成镜像 `ubuntu:noble`。这种方式更适合制作自定义基础镜像或把现成的根文件系统快速封装成镜像。 导入成功后,我们可以用 `docker image ls` 看到这个导入的镜像: ```bash $ docker image ls ubuntu REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu noble 81ec9a55a92a 5 seconds ago 78MB ``` 如果需要在导入时补上镜像元数据,可以配合 `--change` 选项: ```bash $ docker import \ --change 'CMD ["/bin/bash"]' \ --change 'ENV LANG=C.UTF-8' \ rootfs.tar \ custom/base:noble ``` ### 4.6.2 Docker 镜像的导入和导出 `docker save` 和 `docker load` Docker 还提供了 `docker save` 和 `docker load` 命令,用以将镜像保存为一个归档文件,然后传输到另一个位置上,再加载进来。它们仍然适合离线备份、气隙环境分发,或在两台主机之间手工迁移镜像;如果是团队常规分发、版本管理和协作,优先使用 Docker Registry(无论是 Docker Hub 还是内网私有 Registry)会更合适。 #### 保存镜像 使用 `docker save` 命令可以将镜像保存为归档文件。归档中会包含镜像的父层以及所指定的标签;如果本地镜像仓库里已有多个平台变体,还可以通过 `--platform` 仅导出某个平台版本。 比如我们希望保存这个 `alpine` 镜像。 ```bash $ docker image ls alpine REPOSITORY TAG IMAGE ID CREATED SIZE alpine latest baa5d63471ea 5 weeks ago 4.803 MB ``` > **版本提示**:`alpine:latest` 为最新版本的 Alpine Linux。如果需要特定版本号(如 `alpine:3.20`),可以明确指定以确保可重现性。 保存镜像的命令为: ```bash $ docker image save -o filename alpine $ file filename filename: POSIX tar archive ``` 这里的 filename 可以为任意名称甚至任意后缀名,但文件的本质都是归档文件 **注意:如果同名则会覆盖 (没有警告)** 若使用 `gzip` 压缩: ```bash $ docker image save alpine | gzip > alpine-latest.tar.gz ``` 然后我们将 `alpine-latest.tar.gz` 文件复制到了另一个机器上,可以用下面这个命令加载镜像: ```bash $ docker image load -i alpine-latest.tar.gz Loaded image: alpine:latest ``` `docker load` 会恢复归档中的镜像和标签;同样地,在需要时也可以通过 `--platform` 只加载其中一个平台变体。 如果我们结合这两个命令以及 `ssh` 甚至 `pv` 的话,利用 Linux 强大的管道,我们可以写一个命令完成从一个机器将镜像迁移到另一个机器,并且带进度条的功能: ```bash docker save <镜像名> | bzip2 | pv | ssh <用户名>@<主机名> 'cat | docker load' ```