保存和共享镜像
让 Docker 引以为傲的是它能够实现相比于其他虚拟化软件更快的环境迁移和部署,在这件事情上,轻量级的容器和镜像结构的设计无疑发挥了巨大的作用。通过将容器打包成镜像,再利用体积远小于其他虚拟化软件的 Docker 镜像,我们可以更快的将它们复制到其他的机器上。
Docker 镜像的本质是多个基于 UnionFS 的镜像层依次挂载的结果,而容器的文件系统则是在以只读方式挂载镜像后增加的一个可读可写的沙盒环境。
基于这样的结构,Docker 中为我们提供了将容器中的这个可读可写的沙盒环境持久化为一个镜像层的方法。更浅显的说,就是我们能够很轻松的在 Docker 里将容器内的修改记录下来,保存为一个新的镜像。
将容器修改的内容保存为镜像的命令是 docker commit,由于镜像的结构很像代码仓库里的修改记录,而记录容器修改的过程又像是在提交代码,所以这里我们更形象的称之为提交容器的更改。就好比 git commit 一样
docker commit nginx2(docker commit -m "Configured" nginx2 添加个注释)
sha256:be60f0296bcb0226a4360cb4beee9bfe0d058efd6cb5d1e17fffcbf56ee69d2e
Docker 执行将容器内沙盒文件系统记录成镜像层的时候,会先暂停容器的运行,以保证容器内的文件系统处于一个相对稳定的状态,确保数据的一致性。
使用 docker images 可以看到一个 IMAGE ID 为 be60f0296bcb0 的新镜像
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> be60f0296bcb 20 seconds ago 109MB
很奇怪的是 他没有REPOSITORY 和 TAG,没有名字是很难在意识当中认识的很清楚的。
为它起个名字吧: docker tag be60f0296bcb nginx2
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx2 latest be60f0296bcb 6 minutes ago 109MB
除了使用 docker tag 在容器提交为新的镜像后为镜像命名这种方式外,我们还可以直接在 docker commit 命令里指定新的镜像名,这种方式在使用容器提交时会更加方便。
$ sudo docker commit -m "Upgrade" nginx2 nginx2
镜像的迁移
由于 Docker 是以集中的方式管理镜像的,所以在迁移之前,我们要先从 Docker 中取出镜像。docker save 命令可以将镜像输出,提供了一种让我们保存镜像到 Docker 外部的方式。
docker save nginx2 > nginx2.tar
或者
docker save -o ./nginx2.tar nginx2
可以用命令 tar -tf nginx2.tar 查看导出的包里面的文件
a41de46967ff48a21a6e987fc0dc4cdb8e64aa6d10cca59c27995ed246236af/
3a41de46967ff48a21a6e987fc0dc4cdb8e64aa6d10cca59c27995ed246236af/VERSION
3a41de46967ff48a21a6e987fc0dc4cdb8e64aa6d10cca59c27995ed246236af/json
3a41de46967ff48a21a6e987fc0dc4cdb8e64aa6d10cca59c27995ed246236af/layer.tar
7138e00e904539409a1a0164053f71c7af3ebbf997ccb9459369eacca6feb5c3/
7138e00e904539409a1a0164053f71c7af3ebbf997ccb9459369eacca6feb5c3/VERSION
7138e00e904539409a1a0164053f71c7af3ebbf997ccb9459369eacca6feb5c3/json
7138e00e904539409a1a0164053f71c7af3ebbf997ccb9459369eacca6feb5c3/layer.tar
be60f0296bcb0226a4360cb4beee9bfe0d058efd6cb5d1e17fffcbf56ee69d2e.json
e0dd7477866f61c62c19bcec79b7b65011a63fb5b025bfeb4e6503ce26c096b8/
e0dd7477866f61c62c19bcec79b7b65011a63fb5b025bfeb4e6503ce26c096b8/VERSION
e0dd7477866f61c62c19bcec79b7b65011a63fb5b025bfeb4e6503ce26c096b8/json
e0dd7477866f61c62c19bcec79b7b65011a63fb5b025bfeb4e6503ce26c096b8/layer.tar
e9dbab7b1f2902baaf799ccb746ce407c4be38c7231f4e6998f3c18a372c2e2f/
e9dbab7b1f2902baaf799ccb746ce407c4be38c7231f4e6998f3c18a372c2e2f/VERSION
e9dbab7b1f2902baaf799ccb746ce407c4be38c7231f4e6998f3c18a372c2e2f/json
e9dbab7b1f2902baaf799ccb746ce407c4be38c7231f4e6998f3c18a372c2e2f/layer.tar
manifest.json
repositories
你会看到里面其实就是镜像所基于的几个镜像层的记录文件
导入镜像
如果你跟我一样在同一台机上玩docker 可以先删掉 原来的镜像
docker rmi nginx2
然后导入
docker load < nginx2.tar
或者
docker load -i nginx2.tar
镜像导入后,我们就可以通过 docker images 看到它了,导入的镜像会延用原有的镜像名称。
批量迁移
通过 docker save 和 docker load 命令我们还能够批量迁移镜像,只要我们在 docker save 中传入多个镜像名作为参数,它就能够将这些镜像都打成一个包,便于我们一次性迁移多个镜像。
$ sudo docker save -o ./images.tar nginx:1.0 nginx2:1.12 mysql1:5.7
装有多个镜像的包可以直接被 docker load 识别和读取,我们将这个包导入后,所有其中装载的镜像都会被导入到 Docker 之中。
导入导出容器
docker export -o ./nginx_container.tar nginx2