Docker StorageDriver
Docker 对 container 的使用基本是建立在 LXC 基础之上,然而 LXC 存在的问题是难以通过标准化的模板去制作、重建、复制和移动 container。
在以 VM 为基础的虚拟化中,有 image 和 snapshot 可以用于 VM 的复制、重建以及移动的功能。
想要通过 container 来实现快速的大规模部署和更新,这些功能不可或缺。
在 Docker 0.7 中引入了 Storage Driver(储存驱动), 现在已经支持 AUFS、Btrfs、Device Mapper、OverlayFS、ZFS、VFS。
一、文件系统
Union File System
简称 Union FS(联合文件系统),可以将不同物理位置的目录合并挂载(mount)到同一目录下。使其从外面看起来像一个文件系统。
例如把一张 CD/DVD 和一个硬盘目录给联合 mount 在一起,然后你就可以对这个只读的 CD/DVD 上的文件进行修改(修改的文件存于硬盘上的目录里)
- Introduce UnionFS
- Union file systems: Implementations, part I
- Union file systems: Implementations, part 2
- Another union filesystem approach
- Unioning file systems: Architecture, features, and design choices
Overlay2
Overlay2 是一种 Union FS
下图显示了 Docker 镜像和 Docker 容器的分层方式。镜像层是 lowerdir,容器层是 upperdir,如果镜像有多个层,则使用多个 lowerdir 目录。统一视图通过名为 merged 的目录公开,该目录实际上是容器挂载点。
在 Overlay2 文件系统中,有四个重要概念:
- lowerdir:下层目录,是一个只读的目录,其中包含了基础文件系统的内容
- upperdir:上层目录,是一个可写的目录,用于存储对底层目录的更改和新增文件
- workdir:工作目录,用于存储挂载过程中的临时文件和元数据。它是一个必需的目录,在挂载过程中会被创建并使用,挂载完成后会被自动删除
- merged:合并目录,即最终的挂载点。它是 lowerdir 和 upperdir 合并后的结果,包含了两者的文件和目录
使用 mount 命令挂载 overlay 文件系统时,需要指定这四个参数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
sudo apt install -y tree mkdir -p lowerdir lowerdir2 upperdir workdir merged echo lowerdir > lowerdir/temp echo lowerdir2 > lowerdir2/temp echo upperdir > upperdir/temp touch lowerdir/l lowerdir2/l2 upperdir/u tree sudo mount -t overlay overlay -o lowerdir=lowerdir:lowerdir2,upperdir=upperdir,workdir=workdir merged tree merged # 可以看到内容是 upperdir cat merged/temp # 在 merged 下新建 m,可以看到 m 在 upperdir 目录中 touch merged/m && tree sudo umount merged
lower 的深度限制 maxDepth:https://github.com/moby/moby/blob/master/daemon/graphdriver/overlay2/overlay.go#L73
二、Linux 系统启动
典型的 Linux 启动到运行需要两个 FS:bootfs + rootfs
bootfs(boot file system):
主要包含 bootloader 和 kernel,bootloader 主要是引导加载 kernel,当 kernel 被加载到内存中后,bootfs 就被 umount 了,此时内存的使用权已由 bootfs 转交给 rootfs。
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 层中。
四、/var/lib/docker
删除 docker 数据,重启 docker,查看 /var/lib/docker 目录
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
sudo rm -rf /var/lib/docker/* sudo service docker restart sudo tree -augpAL 3 /var/lib/docker [drwx--x--- root root] /var/lib/docker ├── [drwx--x--x root root] buildkit │ ├── [-rw------- root root] cache.db │ ├── [-rw-r--r-- root root] containerdmeta.db │ ├── [drwxr-xr-x root root] content │ │ └── [drwxr-xr-x root root] ingest │ ├── [drwx--x--x root root] executor │ ├── [-rw------- root root] history.db │ ├── [-rw------- root root] metadata_v2.db │ └── [-rw------- root root] snapshots.db ├── [drwx--x--- root root] containers ├── [-rw------- root root] engine-id ├── [drwx------ root root] image │ └── [drwx------ root root] overlay2 │ ├── [drwx------ root root] distribution │ ├── [drwx------ root root] imagedb │ ├── [drwx------ root root] layerdb │ └── [-rw------- root root] repositories.json ├── [drwxr-x--- root root] network │ └── [drwxr-x--- root root] files │ └── [-rw-r--r-- root root] local-kv.db ├── [drwx--x--- root root] overlay2 │ └── [drwx------ root root] l ├── [drwx------ root root] plugins │ ├── [drwxr-xr-x root root] storage │ │ └── [drwxr-xr-x root root] ingest │ └── [drwx------ root root] tmp ├── [drwx------ root root] runtimes ├── [drwx------ root root] swarm ├── [drwx------ root root] tmp └── [drwx-----x root root] volumes ├── [brw------- root root] backingFsBlockDev └── [-rw------- root root] metadata.db 23 directories, 10 files
下载镜像,/var/lib/docker/overlay2 下会新增文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
docker pull hello-world sudo tree -augpAL 3 /var/lib/docker [drwx--x--- root root] /var/lib/docker ├── [drwx--x--x root root] buildkit │ ├── [-rw------- root root] cache.db │ ├── [-rw-r--r-- root root] containerdmeta.db │ ├── [drwxr-xr-x root root] content │ │ └── [drwxr-xr-x root root] ingest │ ├── [drwx--x--x root root] executor │ ├── [-rw------- root root] history.db │ ├── [-rw------- root root] metadata_v2.db │ └── [-rw------- root root] snapshots.db ├── [drwx--x--- root root] containers ├── [-rw------- root root] engine-id ├── [drwx------ root root] image │ └── [drwx------ root root] overlay2 │ ├── [drwx------ root root] distribution │ ├── [drwx------ root root] imagedb │ ├── [drwx------ root root] layerdb │ └── [-rw------- root root] repositories.json ├── [drwxr-x--- root root] network │ └── [drwxr-x--- root root] files │ └── [-rw-r--r-- root root] local-kv.db ├── [drwx--x--- root root] overlay2 │ ├── [drwx--x--- root root] 56eec5fda1c707691c75293c6cf0cc48932325b9eb5b3d49a5773175df97e4c7 │ │ ├── [drwxr-xr-x root root] diff │ │ └── [-rw-r--r-- root root] link │ └── [drwx------ root root] l │ └── [lrwxrwxrwx root root] AJVRY4BDWHUFJCD4PYZX264TCD -> ../56eec5fda1c707691c75293c6cf0cc48932325b9eb5b3d49a5773175df97e4c7/diff ├── [drwx------ root root] plugins │ ├── [drwxr-xr-x root root] storage │ │ └── [drwxr-xr-x root root] ingest │ └── [drwx------ root root] tmp ├── [drwx------ root root] runtimes ├── [drwx------ root root] swarm ├── [drwx------ root root] tmp └── [drwx-----x root root] volumes ├── [brw------- root root] backingFsBlockDev └── [-rw------- root root] metadata.db 26 directories, 11 files
运行容器,/var/lib/docker/containers 下会新增文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
docker run hello-world sudo tree -augpAL 3 /var/lib/docker [drwx--x--- root root] /var/lib/docker ├── [drwx--x--x root root] buildkit │ ├── [-rw------- root root] cache.db │ ├── [-rw-r--r-- root root] containerdmeta.db │ ├── [drwxr-xr-x root root] content │ │ └── [drwxr-xr-x root root] ingest │ ├── [drwx--x--x root root] executor │ ├── [-rw------- root root] history.db │ ├── [-rw------- root root] metadata_v2.db │ └── [-rw------- root root] snapshots.db ├── [drwx--x--- root root] containers │ └── [drwx--x--- root root] fe85985b4136d2b8041c4a3f99962f599181ec1aac858d55d8f38b6d4020fc3f │ ├── [drwx------ root root] checkpoints │ ├── [-rw------- root root] config.v2.json │ ├── [-rw-r----- root root] fe85985b4136d2b8041c4a3f99962f599181ec1aac858d55d8f38b6d4020fc3f-json.log │ ├── [-rw------- root root] hostconfig.json │ ├── [-rw-r--r-- root root] hostname │ ├── [-rw-r--r-- root root] hosts │ ├── [drwx--x--- root root] mounts │ ├── [-rw-r--r-- root root] resolv.conf │ └── [-rw-r--r-- root root] resolv.conf.hash ├── [-rw------- root root] engine-id ├── [drwx------ root root] image │ └── [drwx------ root root] overlay2 │ ├── [drwx------ root root] distribution │ ├── [drwx------ root root] imagedb │ ├── [drwx------ root root] layerdb │ └── [-rw------- root root] repositories.json ├── [drwxr-x--- root root] network │ └── [drwxr-x--- root root] files │ └── [-rw-r--r-- root root] local-kv.db ├── [drwx--x--- root root] overlay2 │ ├── [drwx--x--- root root] 56eec5fda1c707691c75293c6cf0cc48932325b9eb5b3d49a5773175df97e4c7 │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ └── [-rw-r--r-- root root] link │ ├── [drwx--x--- root root] 8607abf841bb20751aa5ac44f83692260977e2b7684776058be5512c4b151254 │ │ ├── [drwxr-xr-x root root] diff │ │ ├── [-rw-r--r-- root root] link │ │ ├── [-rw-rw-rw- root root] lower │ │ └── [drwx------ root root] work │ ├── [drwx--x--- root root] 8607abf841bb20751aa5ac44f83692260977e2b7684776058be5512c4b151254-init │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ ├── [-rw-r--r-- root root] link │ │ ├── [-rw-rw-rw- root root] lower │ │ └── [drwx------ root root] work │ └── [drwx------ root root] l │ ├── [lrwxrwxrwx root root] AAK6FNEKCJEQTTAL7R5HO24IZY -> ../8607abf841bb20751aa5ac44f83692260977e2b7684776058be5512c4b151254/diff │ ├── [lrwxrwxrwx root root] AJVRY4BDWHUFJCD4PYZX264TCD -> ../56eec5fda1c707691c75293c6cf0cc48932325b9eb5b3d49a5773175df97e4c7/diff │ └── [lrwxrwxrwx root root] WILBHTRJ2TEEON5LGYIPSZWGPE -> ../8607abf841bb20751aa5ac44f83692260977e2b7684776058be5512c4b151254-init/diff ├── [drwx------ root root] plugins │ ├── [drwxr-xr-x root root] storage │ │ └── [drwxr-xr-x root root] ingest │ └── [drwx------ root root] tmp ├── [drwx------ root root] runtimes ├── [drwx------ root root] swarm ├── [drwx------ root root] tmp └── [drwx-----x root root] volumes ├── [brw------- root root] backingFsBlockDev └── [-rw------- root root] metadata.db 37 directories, 24 files
删除容器,/var/lib/docker/containers 下会被删除
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
docker rm fe85985b4136 sudo tree -augpAL 3 /var/lib/docker [drwx--x--- root root] /var/lib/docker ├── [drwx--x--x root root] buildkit │ ├── [-rw------- root root] cache.db │ ├── [-rw-r--r-- root root] containerdmeta.db │ ├── [drwxr-xr-x root root] content │ │ └── [drwxr-xr-x root root] ingest │ ├── [drwx--x--x root root] executor │ ├── [-rw------- root root] history.db │ ├── [-rw------- root root] metadata_v2.db │ └── [-rw------- root root] snapshots.db ├── [drwx--x--- root root] containers ├── [-rw------- root root] engine-id ├── [drwx------ root root] image │ └── [drwx------ root root] overlay2 │ ├── [drwx------ root root] distribution │ ├── [drwx------ root root] imagedb │ ├── [drwx------ root root] layerdb │ └── [-rw------- root root] repositories.json ├── [drwxr-x--- root root] network │ └── [drwxr-x--- root root] files │ └── [-rw-r--r-- root root] local-kv.db ├── [drwx--x--- root root] overlay2 │ ├── [drwx--x--- root root] 56eec5fda1c707691c75293c6cf0cc48932325b9eb5b3d49a5773175df97e4c7 │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ └── [-rw-r--r-- root root] link │ └── [drwx------ root root] l │ └── [lrwxrwxrwx root root] AJVRY4BDWHUFJCD4PYZX264TCD -> ../56eec5fda1c707691c75293c6cf0cc48932325b9eb5b3d49a5773175df97e4c7/diff ├── [drwx------ root root] plugins │ ├── [drwxr-xr-x root root] storage │ │ └── [drwxr-xr-x root root] ingest │ └── [drwx------ root root] tmp ├── [drwx------ root root] runtimes ├── [drwx------ root root] swarm ├── [drwx------ root root] tmp └── [drwx-----x root root] volumes ├── [brw------- root root] backingFsBlockDev └── [-rw------- root root] metadata.db 26 directories, 12 files
删除镜像,/var/lib/docker/overlay2 下会被删除
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
docker rmi hello-world sudo tree -augpAL 3 /var/lib/docker [drwx--x--- root root] /var/lib/docker ├── [drwx--x--x root root] buildkit │ ├── [-rw------- root root] cache.db │ ├── [-rw-r--r-- root root] containerdmeta.db │ ├── [drwxr-xr-x root root] content │ │ └── [drwxr-xr-x root root] ingest │ ├── [drwx--x--x root root] executor │ ├── [-rw------- root root] history.db │ ├── [-rw------- root root] metadata_v2.db │ └── [-rw------- root root] snapshots.db ├── [drwx--x--- root root] containers ├── [-rw------- root root] engine-id ├── [drwx------ root root] image │ └── [drwx------ root root] overlay2 │ ├── [drwx------ root root] distribution │ ├── [drwx------ root root] imagedb │ ├── [drwx------ root root] layerdb │ └── [-rw------- root root] repositories.json ├── [drwxr-x--- root root] network │ └── [drwxr-x--- root root] files │ └── [-rw-r--r-- root root] local-kv.db ├── [drwx--x--- root root] overlay2 │ └── [drwx------ root root] l ├── [drwx------ root root] plugins │ ├── [drwxr-xr-x root root] storage │ │ └── [drwxr-xr-x root root] ingest │ └── [drwx------ root root] tmp ├── [drwx------ root root] runtimes ├── [drwx------ root root] swarm ├── [drwx------ root root] tmp └── [drwx-----x root root] volumes ├── [brw------- root root] backingFsBlockDev └── [-rw------- root root] metadata.db 23 directories, 10 files
/var/lib/docker/containers/xxx/ 下的文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
docker run --restart=always --name mysql -e MYSQL_ROOT_PASSWORD=root -e MYSQL_ROOT_HOST=% -e TZ=Asia/Shanghai -p 3306:3306 -d mysql:latest 4f31377834851b73301378bc4e354237dee0cbe736311588463cab0f0fa37b01 sudo tree -augpAL 3 /var/lib/docker [drwx--x--- root root] /var/lib/docker ├── [drwx--x--x root root] buildkit │ ├── [-rw------- root root] cache.db │ ├── [-rw-r--r-- root root] containerdmeta.db │ ├── [drwxr-xr-x root root] content │ │ └── [drwxr-xr-x root root] ingest │ ├── [drwx--x--x root root] executor │ ├── [-rw------- root root] history.db │ ├── [-rw------- root root] metadata_v2.db │ └── [-rw------- root root] snapshots.db ├── [drwx--x--- root root] containers │ └── [drwx--x--- root root] 4f31377834851b73301378bc4e354237dee0cbe736311588463cab0f0fa37b01 │ ├── [-rw-r----- root root] 4f31377834851b73301378bc4e354237dee0cbe736311588463cab0f0fa37b01-json.log │ ├── [drwx------ root root] checkpoints │ ├── [-rw------- root root] config.v2.json │ ├── [-rw------- root root] hostconfig.json │ ├── [-rw-r--r-- root root] hostname │ ├── [-rw-r--r-- root root] hosts │ ├── [drwx--x--- root root] mounts │ ├── [-rw-r--r-- root root] resolv.conf │ └── [-rw-r--r-- root root] resolv.conf.hash ├── [-rw------- root root] engine-id ├── [drwx------ root root] image │ └── [drwx------ root root] overlay2 │ ├── [drwx------ root root] distribution │ ├── [drwx------ root root] imagedb │ ├── [drwx------ root root] layerdb │ └── [-rw------- root root] repositories.json ├── [drwxr-x--- root root] network │ └── [drwxr-x--- root root] files │ └── [-rw-r--r-- root root] local-kv.db ├── [drwx--x--- root root] overlay2 │ ├── [drwx--x--- root root] 01733b232b0bb9e61c3b1d91094f3cfaab0dcb393533a9561cd00838a088def0 │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ ├── [-rw-r--r-- root root] link │ │ ├── [-rw-rw-rw- root root] lower │ │ └── [drwx------ root root] work │ ├── [drwx--x--- root root] 034b57a460ccf5ebd5ae6fff8fc138551c569b155a4ef756a3b3adbaf449d838 │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ ├── [-rw-r--r-- root root] link │ │ ├── [-rw-rw-rw- root root] lower │ │ └── [drwx------ root root] work │ ├── [drwx--x--- root root] 07ba108168e36ca5f72283f46d98b29dbbf392666be45ba221ea940ca862a417 │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ ├── [-rw-r--r-- root root] link │ │ ├── [-rw-rw-rw- root root] lower │ │ └── [drwx------ root root] work │ ├── [drwx--x--- root root] 0da140a0222f765e9fb73620eb93ac89b2096a35a0a5a6ae933ec0ad8e4d2e62 │ │ ├── [drwxr-xr-x root root] diff │ │ ├── [-rw-r--r-- root root] link │ │ ├── [-rw-rw-rw- root root] lower │ │ ├── [drwxr-xr-x root root] merged │ │ └── [drwx------ root root] work │ ├── [drwx--x--- root root] 0da140a0222f765e9fb73620eb93ac89b2096a35a0a5a6ae933ec0ad8e4d2e62-init │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ ├── [-rw-r--r-- root root] link │ │ ├── [-rw-rw-rw- root root] lower │ │ └── [drwx------ root root] work │ ├── [drwx--x--- root root] 175f333ff0891c602fecb87292686821c90ef96120df6c16a61fc438690841c9 │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ ├── [-rw-r--r-- root root] link │ │ ├── [-rw-rw-rw- root root] lower │ │ └── [drwx------ root root] work │ ├── [drwx--x--- root root] 19c4e084eb8c38be7f2a2754ace8d19842e1e29ca41e06ccfb0908006cc42608 │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ ├── [-rw-r--r-- root root] link │ │ ├── [-rw-rw-rw- root root] lower │ │ └── [drwx------ root root] work │ ├── [drwx--x--- root root] 2a7d4ecf76ef8b76b5d76676334468e9a77464441cc54ccd493624e58d60c423 │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ ├── [-rw-r--r-- root root] link │ │ ├── [-rw-rw-rw- root root] lower │ │ └── [drwx------ root root] work │ ├── [drwx--x--- root root] 3e135838ec038517b30bb94fd6d65ee360b63b539624ab4e7c4a1c0839108f56 │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ ├── [-rw-r--r-- root root] link │ │ ├── [-rw-rw-rw- root root] lower │ │ └── [drwx------ root root] work │ ├── [drwx--x--- root root] 4e12d0dcedf7c5d4ee9585364e6fb34820a2d07006216bc573ee155b7cf6435f │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ ├── [-rw-r--r-- root root] link │ │ ├── [-rw-rw-rw- root root] lower │ │ └── [drwx------ root root] work │ ├── [drwx--x--- root root] 8fd048c3f3058286313a5612e4d0ce0bb4d74291c182c503346c3f2e23903979 │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ └── [-rw-r--r-- root root] link │ ├── [drwx--x--- root root] 9891fa6521802a525785693b721672e26137007c8c9709a0dac62402ff73cd7e │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ ├── [-rw-r--r-- root root] link │ │ ├── [-rw-rw-rw- root root] lower │ │ └── [drwx------ root root] work │ ├── [drwx--x--- root root] abe0b2e6acd96862c74201805b73a7e7a60cfcff6d528b331266bc20e42fed4c │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ ├── [-rw-r--r-- root root] link │ │ ├── [-rw-rw-rw- root root] lower │ │ └── [drwx------ root root] work │ ├── [drwx--x--- root root] d9ca5aa21a93f0b14edb7f3ec899f113091e4eef7ba340f3ea8a537c57491c8c │ │ ├── [-rw------- root root] committed │ │ ├── [drwxr-xr-x root root] diff │ │ ├── [-rw-r--r-- root root] link │ │ ├── [-rw-rw-rw- root root] lower │ │ └── [drwx------ root root] work │ └── [drwx------ root root] l │ ├── [lrwxrwxrwx root root] 2AKWTAQ3QIMSCXORDH25FAS3O7 -> ../d9ca5aa21a93f0b14edb7f3ec899f113091e4eef7ba340f3ea8a537c57491c8c/diff │ ├── [lrwxrwxrwx root root] 3Y6F3ZLWWTCB3USOSHPQD27OUS -> ../3e135838ec038517b30bb94fd6d65ee360b63b539624ab4e7c4a1c0839108f56/diff │ ├── [lrwxrwxrwx root root] BRPLZX3BCN57DYDEZODSRMI2HO -> ../0da140a0222f765e9fb73620eb93ac89b2096a35a0a5a6ae933ec0ad8e4d2e62/diff │ ├── [lrwxrwxrwx root root] DXDRY2ODMLCDFVOR7MQA2DWH4A -> ../2a7d4ecf76ef8b76b5d76676334468e9a77464441cc54ccd493624e58d60c423/diff │ ├── [lrwxrwxrwx root root] G3HCZ2KFRYM7C6XBJ4UBFXPLCI -> ../175f333ff0891c602fecb87292686821c90ef96120df6c16a61fc438690841c9/diff │ ├── [lrwxrwxrwx root root] G4FRKLZU3DTTGK2T2T4BMUUDN3 -> ../8fd048c3f3058286313a5612e4d0ce0bb4d74291c182c503346c3f2e23903979/diff │ ├── [lrwxrwxrwx root root] LV5RVCKIRBRCYXVHBSVKMX2GAI -> ../4e12d0dcedf7c5d4ee9585364e6fb34820a2d07006216bc573ee155b7cf6435f/diff │ ├── [lrwxrwxrwx root root] ND7FYBAZM7NCLDYEPQBUWYS6TN -> ../07ba108168e36ca5f72283f46d98b29dbbf392666be45ba221ea940ca862a417/diff │ ├── [lrwxrwxrwx root root] POCRW5BVS5AC2QGIVIW6RMVZJE -> ../01733b232b0bb9e61c3b1d91094f3cfaab0dcb393533a9561cd00838a088def0/diff │ ├── [lrwxrwxrwx root root] R3DP23DR3CKYQA5SOALIW2S5US -> ../19c4e084eb8c38be7f2a2754ace8d19842e1e29ca41e06ccfb0908006cc42608/diff │ ├── [lrwxrwxrwx root root] RSNYJDKGE6RIFORC6BSKH6VSK2 -> ../0da140a0222f765e9fb73620eb93ac89b2096a35a0a5a6ae933ec0ad8e4d2e62-init/diff │ ├── [lrwxrwxrwx root root] TCZU475LZP3EAQL5UHDASLFPPA -> ../abe0b2e6acd96862c74201805b73a7e7a60cfcff6d528b331266bc20e42fed4c/diff │ ├── [lrwxrwxrwx root root] WBFZLP62AQJMSJMX7Y2C4NFO4L -> ../9891fa6521802a525785693b721672e26137007c8c9709a0dac62402ff73cd7e/diff │ └── [lrwxrwxrwx root root] YLK4O3EQQPNR7LV25XN7BD6NRF -> ../034b57a460ccf5ebd5ae6fff8fc138551c569b155a4ef756a3b3adbaf449d838/diff ├── [drwx------ root root] plugins │ ├── [drwxr-xr-x root root] storage │ │ └── [drwxr-xr-x root root] ingest │ └── [drwx------ root root] tmp ├── [drwx------ root root] runtimes ├── [drwx------ root root] swarm ├── [drwx------ root root] tmp └── [drwx-----x root root] volumes ├── [drwx-----x root root] 5c76d178f23ac14b8a117b8cea75dbd46c4df2598465e29b678571213623f067 │ └── [drwxrwxrwt 999 systemd-journal] _data ├── [brw------- root root] backingFsBlockDev └── [-rw------- root root] metadata.db 84 directories, 57 files sudo tree -augpAL 1 /var/lib/docker/overlay2/0da140a0222f765e9fb73620eb93ac89b2096a35a0a5a6ae933ec0ad8e4d2e62/merged [drwxr-xr-x root root] /var/lib/docker/overlay2/0da140a0222f765e9fb73620eb93ac89b2096a35a0a5a6ae933ec0ad8e4d2e62/merged ├── [drwxr-xr-x root root] bin ├── [drwxr-xr-x root root] boot ├── [drwxr-xr-x root root] dev ├── [drwxr-xr-x root root] docker-entrypoint-initdb.d ├── [-rwxr-xr-x root root] .dockerenv ├── [lrwxrwxrwx root root] entrypoint.sh -> usr/local/bin/docker-entrypoint.sh ├── [drwxr-xr-x root root] etc ├── [drwxr-xr-x root root] home ├── [drwxr-xr-x root root] lib ├── [drwxr-xr-x root root] lib64 ├── [drwxr-xr-x root root] media ├── [drwxr-xr-x root root] mnt ├── [drwxr-xr-x root root] opt ├── [drwxr-xr-x root root] proc ├── [drwx------ root root] root ├── [drwxr-xr-x root root] run ├── [drwxr-xr-x root root] sbin ├── [drwxr-xr-x root root] srv ├── [drwxr-xr-x root root] sys ├── [drwxrwxrwt root root] tmp ├── [drwxr-xr-x root root] usr └── [drwxr-xr-x root root] var 21 directories, 2 files sudo cat /var/lib/docker/containers/4f31377834851b73301378bc4e354237dee0cbe736311588463cab0f0fa37b01/config.v2.json { "StreamConfig": {}, "State": { "Running": true, "Paused": false, "Restarting": false, "OOMKilled": false, "RemovalInProgress": false, "Dead": false, "Pid": 4267, "ExitCode": 0, "Error": "", "StartedAt": "2024-01-16T02:48:15.473430682Z", "FinishedAt": "0001-01-01T00:00:00Z", "Health": null }, "ID": "4f31377834851b73301378bc4e354237dee0cbe736311588463cab0f0fa37b01", "Created": "2024-01-16T02:48:13.904966606Z", "Managed": false, "Path": "docker-entrypoint.sh", "Args": [ "mysqld" ], "Config": { "Hostname": "4f3137783485", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "3306/tcp": {}, "33060/tcp": {} }, "Tty": false, "OpenStdin": false, "StdinOnce": false, "Env": [ "MYSQL_ROOT_PASSWORD=root", "MYSQL_ROOT_HOST=%", "TZ=Asia/Shanghai", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "GOSU_VERSION=1.12", "MYSQL_MAJOR=8.0", "MYSQL_VERSION=8.0.27-1debian10" ], "Cmd": [ "mysqld" ], "Image": "mysql:latest", "Volumes": { "/var/lib/mysql": {} }, "WorkingDir": "", "Entrypoint": [ "docker-entrypoint.sh" ], "OnBuild": null, "Labels": {} }, "Image": "sha256:3218b38490cec8d31976a40b92e09d61377359eab878db49f025e5d464367f3b", "ImageManifest": null, "NetworkSettings": { "Bridge": "", "SandboxID": "6c452c63f882a899a003b70dc6646936f6f80b8ec201a64170a2c10b245f5b27", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "cebf478ab715133af49740074ac02abd86cd441452887165531ba548e44a18e1", "EndpointID": "87c29cb428f70557cc449c155b0f5411b86a2ec1f0bacd2aa5096858bb83483d", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02", "DriverOpts": null, "IPAMOperational": false } }, "Service": null, "Ports": { "3306/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "3306" }, { "HostIp": "::", "HostPort": "3306" } ], "33060/tcp": null }, "SandboxKey": "/var/run/docker/netns/6c452c63f882", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "IsAnonymousEndpoint": false, "HasSwarmEndpoint": false }, "LogPath": "/var/lib/docker/containers/4f31377834851b73301378bc4e354237dee0cbe736311588463cab0f0fa37b01/4f31377834851b73301378bc4e354237dee0cbe736311588463cab0f0fa37b01-json.log", "Name": "/mysql", "Driver": "overlay2", "OS": "linux", "RestartCount": 0, "HasBeenStartedBefore": true, "HasBeenManuallyStopped": false, "MountPoints": { "/var/lib/mysql": { "Source": "", "Destination": "/var/lib/mysql", "RW": true, "Name": "5c76d178f23ac14b8a117b8cea75dbd46c4df2598465e29b678571213623f067", "Driver": "local", "Type": "volume", "ID": "74b2ff7fe907e282f24823fe261085d24822698ac73224756ee4654a851af659", "Spec": {}, "SkipMountpointCreation": false } }, "SecretReferences": null, "ConfigReferences": null, "MountLabel": "", "ProcessLabel": "", "AppArmorProfile": "", "SeccompProfile": "", "NoNewPrivileges": false, "HostnamePath": "/var/lib/docker/containers/4f31377834851b73301378bc4e354237dee0cbe736311588463cab0f0fa37b01/hostname", "HostsPath": "/var/lib/docker/containers/4f31377834851b73301378bc4e354237dee0cbe736311588463cab0f0fa37b01/hosts", "ShmPath": "", "ResolvConfPath": "/var/lib/docker/containers/4f31377834851b73301378bc4e354237dee0cbe736311588463cab0f0fa37b01/resolv.conf", "LocalLogCacheMeta": { "HaveNotifyEnabled": false } } sudo cat /var/lib/docker/containers/4f31377834851b73301378bc4e354237dee0cbe736311588463cab0f0fa37b01/hostconfig.json { "Binds": null, "ContainerIDFile": "", "LogConfig": { "Type": "json-file", "Config": {} }, "NetworkMode": "default", "PortBindings": { "3306/tcp": [ { "HostIp": "", "HostPort": "3306" } ] }, "RestartPolicy": { "Name": "always", "MaximumRetryCount": 0 }, "AutoRemove": false, "VolumeDriver": "", "VolumesFrom": null, "ConsoleSize": [ 35, 122 ], "CapAdd": null, "CapDrop": null, "CgroupnsMode": "host", "Dns": [], "DnsOptions": [], "DnsSearch": [], "ExtraHosts": null, "GroupAdd": null, "IpcMode": "private", "Cgroup": "", "Links": null, "OomScoreAdj": 0, "PidMode": "", "Privileged": false, "PublishAllPorts": false, "ReadonlyRootfs": false, "SecurityOpt": null, "UTSMode": "", "UsernsMode": "", "ShmSize": 67108864, "Runtime": "runc", "Isolation": "", "CpuShares": 0, "Memory": 0, "NanoCpus": 0, "CgroupParent": "", "BlkioWeight": 0, "BlkioWeightDevice": [], "BlkioDeviceReadBps": [], "BlkioDeviceWriteBps": [], "BlkioDeviceReadIOps": [], "BlkioDeviceWriteIOps": [], "CpuPeriod": 0, "CpuQuota": 0, "CpuRealtimePeriod": 0, "CpuRealtimeRuntime": 0, "CpusetCpus": "", "CpusetMems": "", "Devices": [], "DeviceCgroupRules": null, "DeviceRequests": null, "MemoryReservation": 0, "MemorySwap": 0, "MemorySwappiness": null, "OomKillDisable": false, "PidsLimit": null, "Ulimits": null, "CpuCount": 0, "CpuPercent": 0, "IOMaximumIOps": 0, "IOMaximumBandwidth": 0, "MaskedPaths": [ "/proc/asound", "/proc/acpi", "/proc/kcore", "/proc/keys", "/proc/latency_stats", "/proc/timer_list", "/proc/timer_stats", "/proc/sched_debug", "/proc/scsi", "/sys/firmware", "/sys/devices/virtual/powercap" ], "ReadonlyPaths": [ "/proc/bus", "/proc/fs", "/proc/irq", "/proc/sys", "/proc/sysrq-trigger" ] } sudo cat /var/lib/docker/containers/4f31377834851b73301378bc4e354237dee0cbe736311588463cab0f0fa37b01/hostname 4f3137783485 sudo cat /var/lib/docker/containers/4f31377834851b73301378bc4e354237dee0cbe736311588463cab0f0fa37b01/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.2 4f3137783485 sudo cat /var/lib/docker/containers/4f31377834851b73301378bc4e354237dee0cbe736311588463cab0f0fa37b01/resolv.conf # This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf: # [network] # generateResolvConf = false nameserver 172.30.160.1 sudo cat /var/lib/docker/containers/4f31377834851b73301378bc4e354237dee0cbe736311588463cab0f0fa37b01/resolv.conf.hash sha256:1204f5aedefdf2b590fb3384410e3b44d7b54ed641d20284d4ada011f41eb072
五、Docker 镜像 commit
docker commit 提交容器副本使之成为一个新的镜像
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 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 目录下没有文件
https://docs.docker.com/storage/storagedriver
https://coolshell.cn/articles/17061.html