镜像概述

镜像是一个分层存储的文件

镜像就是一个软件的运行环境

一个镜像可以重复使用,创建无数个容器

一个不包含 Linux 内核而又精简的 Linux 操作系统

镜像是一种标准化的交付,镜像内包含代码以及软件的运行环境

配置镜像加速

阿里云为每一个开通容器镜像服务的用户免费提供一个镜像加速地址

# 配置镜像加速
tee /etc/docker/daemon.json << EOF
{
    "registry-mirrors": ["https://265wemgl.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker.service

拉取镜像

我们拉取镜像一般是默认从 Docker Hub 拉取的,但是国内访问 Docker Hub 速度很慢,所以我们在前面配置了阿里云的镜像加速。在拉取镜像时,直接从阿里云的 Docker 镜像仓库拉取。我们假如要拉取一个镜像,但是不知道仓库中是否有这个镜像时,我们可以先搜索这个镜像名字,看是否有对应的镜像

# 搜索镜像
docker search nginx

# 拉取镜像,如果不指定版本号,默认拉取最新(latest)
docker pull nginx:1.17

镜像拉取到宿主机本地之后,会以分层的文件形式存储,下面是镜像的存放目录

[root@localhost ~]# ll /var/lib/docker/overlay2/
total 0
drwx------ 4 root root     55 Jun 17 19:04 5f4badc01c88554e78d4aaec269a84fb5e2028d42278d5f131dda81c4209622c
drwx------ 3 root root     47 Jun 17 19:04 658e3b564ce9017b0bd507f1853702f6cdda4642fdc6fbf4b4d06e34cf9a8c25
drwx------ 3 root root     30 Jun 17 19:09 6d57028d1a60a66afc6959b02e0005ea424182908fadf6aa5ac90f3868c014f7
brw------- 1 root root 253, 0 Jun 17 18:31 backingFsBlockDev
drwx------ 4 root root     72 Jun 17 19:04 d56648ebd71c9bdb68226b4021ec008db3ed537072b3c4f9e77afc51f8108c07
drwx------ 2 root root    142 Jun 17 19:09 l

镜像与容器的联系

当启动一个新容器时,Docker 只加载只读镜像,并在这个只读镜像上面添加一个读写层,即容器层。但我们需要修改容器里面的文件时,会先从镜像层把这个文件拷贝到读写层,然后再执行修改操作

镜像存储核心技术:联合文件系统(UnionFS)

联合文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(uniteseveral directories into a single virtual filesystem)。联合文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。另外,不同 Docker 容器就可以共享一些基础的文件系统层,同时再加上自己独有的改动层,大大提高了存储的效率

Docker 中使用的 AUFS (AnotherUnionFS)就是一种联合文件系统。 AUFS 支持为每一个成员目录(类似 Git 的分支)设定只读(readonly)、读写(readwrite)和写出(whiteout-able)权限, 同时 AUFS 里有一个类似分层的概念, 对只读权限的分支可以逻辑上进行增量地修改(不影响只读部分的)

Docker 目前支持的联合文件系统包括 OverlayFS、AUFS、Btrfs、VFS、ZFS 和 DeviceMapper

镜像存储核心技术:写时复制(COW)

Docker 镜像由多个只读层叠加而成,启动容器时,Docker 会加载只读镜像层并在镜像层顶部添加一个读写层。如果运行中的容器修改了一个已存在的文件,那么该文件将会从只读层复制到读写层,该文件的只读版本任然存在,只是已经被读写层中该文件的副本所隐藏,这就是写时复制机制

镜像常用管理命令

# 列出镜像,-a显示所有镜像
docker image ls

# 在当前目录通过Dockerfile构建镜像
docker build -t "nginx_tomcat" .

# 查看镜像历史
docker image history nginx:1.17

# 显示镜像的详细信息
docker inspect nginx:1.17

# 从镜像仓库拉取镜像
docker pull nginx:1.17

# 推送镜像到镜像仓库
docker pull centos:7.6.1810

# 移除一个或多个镜像
docker image rm centos    
docker image rm $(docker image ls -q)    # 删除全部镜像

# 删除没有被标记或没有被任何容器引用的镜像
docker image prune -af

# 创建一个引用源镜像标记目标镜像
docker tag centos:latest coentos:v1        # 为centos:latest这个镜像打一个标签为coentos:v1

# 导出容器文件系统为tar归档文件
docker export -o centos-export.tar [CONTAINER ID]

# 导入容器文件系统tar归档文件来创建镜像
docker import centos-export.tar

# 保存一个或多个镜像到一个tar归档文件
docker save -o database.tar redis mysql

# 加载镜像来自tar归档或标准输入
docker load -i database.tar

相信许多的初学者看到这里肯定有疑问,这里说明一下 export & import 和 save & load 的区别在哪里

export 和 import 区别

export 的应用场景主要用来制作基础镜像,比如你从一个 CentOS 镜像启动一个容器,然后安装一些软件和进行一些设置后,使用 Docker export 保存为一个基础镜像。然后把这个镜像分发给其他人使用,比如作为基础的开发环境

export:将容器导出为tar归档文件,生成的是该容器的快照,复刻了容器当前的Linux系统环境
import:将tar归档文件导入为镜像
整个过程即:容器-->tar归档文件-->镜像

save 和 load 区别

如果你的应用是使用 docker-compose.yml 编排的多个镜像组合,但你要部署的客户服务器并不能连外网。这时,你可以使用 docker save将用到的镜像打个包,然后拷贝到客户服务器上使用 docker load 载入

save:将镜像导出为tar归档文件,该命令也可以作用于容器,但导出的是容器背后的images
load:将tar归档文件导入为镜像

注意:save 命令生成的 tar 包比 export 命令生成的 tar 包大很多,两组命令不可交叉互用