Docker Image

Docker 对 container 的使用基本是建立在 LXC 基础之上,然而 LXC 存在的问题是难以移动,难以通过标准化的模板去制作、重建、复制和移动 container。

在以 VM 为基础的虚拟化中,有 image 和 snapshot 可以用于 VM 的复制、重建以及移动的功能。

想要通过 container 来实现快速的大规模部署和更新,这些功能不可或缺。

在 Docker 0.7 中引入了 Storage Driver(储存驱动), 现在已经支持 AUFS、Btrfs、Device Mapper、OverlayFS、ZFS、VFS。

一、储存驱动

https://docs.docker.com/storage/storagedriver/select-storage-driver/

1.Union FileSystem

简称 Union FS(联合文件系统),储存驱动的一种。

一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

2.Overlay2

Overlay2 是一种 Union FS,支持为每一个成员目录(AKA branch)设定 readonly、readwrite 和 whiteout-able 权限。

通常 Union FS 有两个用途:

  • 不借助 LVM, RAID 将多个 disk 和挂载到一个目录下。
  • 将一个 readonly 的 branch 和一个 writeable 的 branch 联合在一起,Live CD 正是基于此,可以允许在 OS image 不变的基础上允许用户在其上进行一些写操作。

Docker 在 Overlay2 上构建的 container image 也正是如此。

OverlayFS 将单个 Linux 主机上的两个目录分层,并将它们显示为单个目录。这些目录称为层,统一过程称为联合安装。

Overlay2 原生支持多达 128 OverlayFS 层。

下图显示了 Docker镜像 和 Docker容器 的分层方式。图像层是 lowerdir,容器层是 upperdir。统一视图通过一个被称为 merged 容器挂载点的目录公开。

二、Linux 系统启动

典型的 Linux 启动到运行需要两个FS - bootfs + rootfs (从功能角度而非文件系统角度)

bootfs(boot file system):

主要包含 bootloader 和 kernel,bootloader 主要是引导加载 kernel,当 kernel 被加载到内存中后,bootfs 就被 umount 了,此时内存的使用权已由 bootfs 转交给 kernel。

rootfs (root file system) :

在 bootfs 之上。包含的就是典型 Linux 系统中的 /dev、/proc、/bin、/etc 等标准目录和文件。

由此可见对于不同的 linux 发行版,bootfs 基本是一致的,rootfs 会有差别,,因此不同的发行版可以公用 bootfs。如下图:

 

三、Docker image 结构

典型的 Linux 在启动后,首先将 rootfs 置为 readonly,进行一系列检查, 然后将其切换为 "readwrite" 供用户使用。

在 Docker 中,起初也是将 rootfs 以 readonly 方式加载并检查,然而接下来利用 union mount 将一个 readwrite 文件系统挂载在 readonly 的 rootfs 之上,并且允许再次将下层的 file system 设定为 readonly,并且向上叠加。

这样一组 readonly 和一个 writeable 的结构构成一个 container 的运行目录,每一个被称作一个 Layer。如下图:

得益于 AUFS 的特性,每一个对 readonly 层文件或目录的修改都只会存在于上层的 writeable 层中。

这样,由于不存在竞争, 多个 container 可以共享 readonly 的 layer。

所以 docker 将 readonly 的层称作 image,对于 container 而言整个 rootfs 都是 read-write 的,但事实上所有的修改都写入最上层的 writeable 层中。

image 不保存用户状态,可以用于模板、重建和复制。

某个镜像:

基于该镜像创建的容器:

上层的 image 依赖下层的 image,因此 docker 中把下层的 image 称作父 image,没有父 image 的 image 称作 base image。

因此想要从一个 image 启动一个 container,docker 会先加载其父 image 直到 base image,用户的进程运行在 writeable 的 layer 中。

所有 parent image 中的数据信息以及 ID、网络和 lxc 管理的资源限制等具体 container 的配置,构成一个 docker 概念上的 container。如下图:

Docker image 采用分层结构的好处

共享资源,节省存储空间:有多个镜像都从相同的 base 镜像构建而来,那么宿主机只需在磁盘上保存一份 base 镜像,同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

快速部署:如果要部署多个 container,base image 可以避免多次拷贝。

内存更省:因为多个 container 共享 base image,以及 OS 的 disk 缓存机制,多个 container 中的进程命中缓存内容的几率大大增加。

升级更方便:相比于 copy-on-write 类型的文件系统,base-image 也是可以挂载为可 writeable 的,可以通过更新 base image 而一次性更新其之上的 container。

允许在不更改 base-image 的同时修改其目录中的文件,所有写操作都发生在最上层的 writeable 层中。

四、Docker 镜像 commit

docker commit 提交容器副本使之成为一个新的镜像

# docker commit -m=“提交的描述信息” -a=“作者” 容器ID 要创建的目标镜像名:[标签名]

# 下载镜像
docker pull tomcat
# 启动镜像
docker run -d -p 8080:8080 tomcat
# 查看容器ID
docker ps -a
# 进入容器
docker exec -it a41c393cfa45 /bin/bash
# 删除 tomcat
rm -rf /usr/local/tomcat/webapps/*
# 退出容器
exit
# 生成新镜像
docker commit -m=“没有webapps的tomcat镜像” -a=“jhxxb” a41c393cfa45 jhxxb/tomcat-del:1.0
# 查看生成的新镜像
docker images

# 运行新镜像(需要指定版本,默认为 latest)
docker run -d -p 8080:8080 jhxxb/tomcat-del:1.0

可以看到新镜像的 webapps 目录下没有文件


http://tiewei.github.io/cloud/Docker-Getting-Start/

https://docs.docker.com/storage/storagedriver/overlayfs-driver/#how-the-overlay2-driver-works

猜你喜欢

转载自www.cnblogs.com/jhxxb/p/11430938.html