Docker 镜像

1. 基本概念

联合文件系统(Union File System)是一个轻量级、高性能的分层文件系统,他的特点就是支持将文件的修改变换为一层层增量提交,并且支持将多个不同的文件系统挂在到一个统一的虚拟文件系统下。

Docker 利用联合文件系统能够组合挂载的特性,建立了一套文件系统分层体系。在这套体系中存储着每一个文件的修改历史。

对文件的更新、删除等其他操作,都不是直接作用于被修改的文件上,而是将修改后的文件直接通过联合文件系统的挂载机制替换掉实际访问的文件。而被修改的文件只是不能被程序和用户访问到,但仍然存在于存储器之中。

在 Docker 中,镜像是一个包含应用程序及相关依赖库的文件,在 Docker 容器启动的过程中,它以只读的方式被用于创建容器运行的基础环境。

如果把容器理解为应用程序运行的虚拟环境,那么镜像就是这个环境的持久化副本(存档)。

在 Docker 中,镜像名称主要分为三部分:Namespace / Repository : Tag 。例如:

library/nginx:stable
library/nginx:1.18.0

Copied!

  • Namespace
  • 镜像的名字空间,用于区别构建镜像的组织或个人
  • 我们在构建自己的镜像时,可以将自己的名字或代号放在 Namespace 里
  • Repository
  • 镜像的档案名
  • 通常采用镜像中所包含的应用程序或微服务名字作为镜像的 Repository 名称
  • Tag
  • 镜像的标签,类似于 Git 中的 Tag
  • 通常采用镜像中所包含的应用程序或微服务的版本(Version)来制定。

除了以上三者,每个镜像都有一个独立的 Image ID ,是长度为 64 位的十六进制字符串。

Docker 的镜像是一个分层结构,镜像的每一层都是在原有层的基础上进行改动的。

镜像的分层机制与 Git 的版本控制原理类似,每层镜像都可以被视为一个提交,并拥有独立的 ID,最顶层的 ID 被视为镜像的 ID 。

例如 tomcat:jre8 的镜像的层级关系如下,每一层都是在前一层的基础上进项修改和提交的结果:

^
|   tomcat
|   java
|   buildpack-deps
|   debian
|   scratch

Copied!

scratch 是 Docker 提供的一个基础层,通常被成为 rootfs ,即启动文件系统。

而 bootfs 之上,通常就是操作系统层。


Docker 里的镜像技术还有一个特性:写时复制。

容器运行的沙盒环境其实就是镜像之上的一层新的可读写的镜像层,原有的镜像层以『只读』的方式被衔接在新镜像层的下方。

只有容器中的程序对文件进行修改时,才会将镜像中这个被改动的文件复制到沙盒环境的镜像层中。

2. 获取镜像

除了镜像列表中的信息,还可以通过 docker inspect 命令获得镜像更详细的信息(一大堆信息):

docker inspect nginx:1.10

Copied!

docker inspect 还可以使用 ID,而且只要具有唯一性,可以只给出镜像 ID 的前 N 位即可。

docker inspect 82e97ab0390

Copied!

docker inspect 返回的结果是 JSON 格式字符串,如果只想得到其中某部分信息,可进行过滤:

docker inspect -f {{".Size"}} 82e97a

Copied!

3. 镜像的迁移

镜像的导入/导出是虚拟化过程中最基础的操作。

  • 使用 docker save 命令可将本地镜像库中的镜像导出:
docker save ubuntu:latest > ubuntu.tar

Copied!

  • 另外,docker save 命令支持同事导出多个镜像:
docker save -o image.tar ubuntu:lasted centos:latest

Copied!

  • 要将导出的镜像数据重新导入到本地的镜像仓库中,可以使用 docker load 命令:
docker load -i ubuntu.tar

Copied!

docker load < ubuntu.tar