Docker 原理篇(二)Docker 的镜像引擎 AUFS

前言

此篇博文是笔者所总结的 Docker 系列之一;

本文为作者的原创作品,转载需注明出处;

基础知识

Linux 的 rootfs 和 bootfs

一个典型的 Linux 系统要能运行的话,它至少需要两个文件系统:

  • boot file system (bootfs):包含 boot loader 和 kernel。用户不会修改这个文件系统。实际上,在启动(boot)过程完成后,整个内核都会被加载进内存,此时 bootfs 会被卸载掉从而释放出所占用的内存。同时也可以看出,对于同样内核版本的不同的 Linux 发行版的 bootfs 都是一致的
  • root file system (rootfs):包含典型的目录结构,包括 /dev, /proc, /bin, /etc, /lib, /usr, and /tmp 等再加上要运行用户应用所需要的所有配置文件,二进制文件和库文件。这个文件系统在不同的 Linux 发行版中是不同的

其实相同内核的不同的 Linux 发行版就是rootfs 不同,bootfs 相同,如下图所示,

AUFS

最开始的思想是,在一些不可写的媒介上,比如 CD/DVD 上面 mount 一个便携式硬盘(可写磁盘),将 CD/DVD 的文件 mount 一份镜像到该磁盘上,已达到变相的对该媒介进行更改;既是在保证原有镜像不变的前提下,copy 一份镜像到磁盘,然后将变更保存在该磁盘上;这就是 AUFS 的核心思想;AUFS 正好被 Docker 拿来构建其多层镜像
参考,Docker基础技术:AUFS

Docker 的文件系统

Docker 镜像的 rootfs

  • 所有 Docker 容器都共享主机系统的 bootfs 即 Linux 内核
  • 每个容器有自己的 rootfs,它来自不同的 Linux 发行版的基础镜像,包括 Ubuntu,Debian 和 SUSE 等
  • 所有基于一种基础镜像的容器都共享这种 rootfs

下面我们来看下 Docker 中的多层镜像

  • 创建一个容器web31,并在该容器中执行python app.py启动一个 webapp 应用。

    1
    2
    3
    4
    5
    # 创建一个名为 web31 的容器,会从 docker hub 上下载相关 tranning 镜像
    $ sudo docker create --name web31 training/webapp python app.py
    $ sudo docker ps -ls #查看当前正在运行的 docker 容器
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    2210b152b308 training/webapp "python app.py" 58 minutes ago Created web31
  • 查看traning/webapp镜像由哪些镜像构成

    • history 查找指定镜像的构成历史记录

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      # 首先切换到 root 账户
      $ su - root
      $ docker history training/webapp
      IMAGE CREATED CREATED BY SIZE COMMENT
      6fae60ef3446 19 months ago /bin/sh -c #(nop) CMD ["python" "app.py"] 0 B
      <missing> 19 months ago /bin/sh -c #(nop) EXPOSE 5000/tcp 0 B
      <missing> 19 months ago /bin/sh -c #(nop) WORKDIR /opt/webapp 0 B
      <missing> 19 months ago /bin/sh -c #(nop) ADD dir:9b2a69f6f30d18b02b5 703 B
      <missing> 19 months ago /bin/sh -c pip install -qr /tmp/requirements. 4.363 MB
      <missing> 19 months ago /bin/sh -c #(nop) ADD file:c59059439864153904 41 B
      <missing> 19 months ago /bin/sh -c DEBIAN_FRONTEND=noninteractive apt 135.3 MB
      <missing> 19 months ago /bin/sh -c apt-get update 20.8 MB
      <missing> 19 months ago /bin/sh -c #(nop) MAINTAINER Docker Education 0 B
      <missing> 19 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B
      <missing> 19 months ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/ 1.895 kB
      <missing> 19 months ago /bin/sh -c echo '#!/bin/sh' > /usr/sbin/polic 194.5 kB
      <missing> 19 months ago /bin/sh -c #(nop) ADD file:f4d7b4b3402b5c53f2 188.1 MB
    • /var/lib/docker/aufs/diff/ 镜像存放的位置

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      $ ls -l
      root@ubuntu:/var/lib/docker/aufs/diff# ls -lt
      drwxr-xr-x 4 root root 4096 Dec 19 16:25 5420c2ad6952b5597042f7e3ca75e61333e8bda52eb4b9b0a197c4e4c5547c9e
      drwxr-xr-x 6 root root 4096 Dec 19 16:25 5420c2ad6952b5597042f7e3ca75e61333e8bda52eb4b9b0a197c4e4c5547c9e-init
      drwxr-xr-x 2 root root 4096 Dec 19 16:25 828a1c91a6fb1928559b7b9813c0917affd84fcfa7a4e79476d20623b2c29c2d
      drwxr-xr-x 2 root root 4096 Dec 19 16:25 8d8fd100b49edd233212e17c64c8b5061c2b79eb7f7f2fd5fae36c9bf59a502f
      drwxr-xr-x 2 root root 4096 Dec 19 16:25 9b79d3f46e7826defa1c283d8282f3169c876bde8b6084cdbe60672acacb9274
      drwxr-xr-x 3 root root 4096 Dec 19 16:25 864df82537caf88937c58efbf158f9185ebb872cfb54b15d8888f33561ddaa56
      drwxr-xr-x 3 root root 4096 Dec 19 16:25 a3c07d88c61c220d3cc2e2b317b317dec0be11fd629eab7bd3def680a25686cb
      drwxr-xr-x 3 root root 4096 Dec 19 16:25 e31f34199774f4446ddde561a3e1a3dbbc254e483f1bd7193571b93f776becc4
      drwxr-xr-x 6 root root 4096 Dec 19 16:25 1640c122bc62e1fa893cdeae766952951a934864dacbef3e87d2d9eae68c78d1
      drwxr-xr-x 3 root root 4096 Dec 19 16:24 258cfd490a2345067156a2f43d9425e7d12907ce3df64072e37a17ab18b55248
      drwxr-xr-x 2 root root 4096 Dec 19 16:24 67614ba4f62bb6f949acff511a18447a620d5b0a2c4c293bdeb7cd9e97a6cdbc
      drwxr-xr-x 2 root root 4096 Dec 19 16:24 654940ca942ba450e2c5dd38e10bc462333a0307b8531e3193b9f9cbcb119d16
      drwxr-xr-x 3 root root 4096 Dec 19 16:24 37edd74902c396df578b8fcfd233457fe27efd3e0f871e677ada43a92f0bad79
      drwxr-xr-x 6 root root 4096 Dec 19 16:24 9c0b2e0c1996496f8031c7bf148940e55b34bf7efa067725453430c8db3a27ea
      drwxr-xr-x 21 root root 4096 Dec 19 16:24 5ae0f9c8801e4493a1b5c6a2ba07bf4502e63193603f50681aa07fa5cf992949

      这里,或许会有疑问,training/webapp 不是总共只有 13 层镜像吗?这里怎么显示有 15 层?那是因为容器web31本身包含两层(一层只读、一层可读写镜像),后续会详细描述。

    • 定位training/webapp的基础镜像的目录位置
      由于基础镜像中的 bin 目录会被直接使用,所以,我们可以试着查找 bin 目录中的一个文件来定位基础镜像的目录位置;
      由此可知,目录5ae0f9c8801e4493a1b5c6a2ba07bf4502e63193603f50681aa07fa5cf992949是基础镜像的目录

      1
      2
      root@ubuntu:/var/lib/docker/aufs/diff# find -iname mountpoint
      ./5ae0f9c8801e4493a1b5c6a2ba07bf4502e63193603f50681aa07fa5cf992949/bin/mountpoint
    • 查看基础镜像内容

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      root@ubuntu:/var/lib/docker/aufs/diff# ls -l 5ae0f9c8801e4493a1b5c6a2ba07bf4502e63193603f50681aa07fa5cf992949
      total 76
      drwxr-xr-x 2 root root 4096 Apr 27 2015 bin
      drwxr-xr-x 2 root root 4096 Apr 11 2014 boot
      drwxr-xr-x 3 root root 4096 Apr 27 2015 dev
      drwxr-xr-x 61 root root 4096 Apr 27 2015 etc
      drwxr-xr-x 2 root root 4096 Apr 11 2014 home
      drwxr-xr-x 12 root root 4096 Apr 27 2015 lib
      drwxr-xr-x 2 root root 4096 Apr 27 2015 lib64
      drwxr-xr-x 2 root root 4096 Apr 27 2015 media
      drwxr-xr-x 2 root root 4096 Apr 11 2014 mnt
      drwxr-xr-x 2 root root 4096 Apr 27 2015 opt
      drwxr-xr-x 2 root root 4096 Apr 11 2014 proc
      drwx------ 2 root root 4096 Apr 27 2015 root
      drwxr-xr-x 7 root root 4096 Apr 27 2015 run
      drwxr-xr-x 2 root root 4096 Apr 27 2015 sbin
      drwxr-xr-x 2 root root 4096 Apr 27 2015 srv
      drwxr-xr-x 2 root root 4096 Mar 13 2014 sys
      drwxrwxrwt 2 root root 4096 Apr 27 2015 tmp
      drwxr-xr-x 10 root root 4096 Apr 27 2015 usr
      drwxr-xr-x 11 root root 4096 Apr 27 2015 var

      可见,基础镜像目录中包含了当前虚拟机操作系统所必须的所有rootfs

Docker 的 AUFS 文件系统

关于 Docker的分层镜像,除了 aufs,docker 还支持 btrfs, devicemapper 和 vfs,你可以使用 -s 或 –storage-driver= 选项来指定相关的镜像存储方式;Ubuntu 默认使用的是 AUFS.

  • docker info查看所使用的文件驱动

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    root@ubuntu:/var/lib/docker/aufs/diff# docker info
    Containers: 1
    Running: 0
    Paused: 0
    Stopped: 1
    Images: 1
    Server Version: 1.12.1
    Storage Driver: aufs
    Root Dir: /var/lib/docker/aufs
    Backing Filesystem: extfs
    Dirs: 15
    Dirperm1 Supported: true
    Logging Driver: json-file
    Cgroup Driver: cgroupfs
  • training/webapp镜像的角度,总共有 13 层镜像

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    $ docker images
    REPOSITORY TAG IMAGE ID CREATED SIZE
    training/webapp latest 6fae60ef3446 19 months ago 348.8 MB
    $ docker inspect 6fae60ef3446
    "RootFS": {
    "Type": "layers",
    "Layers": [
    "sha256:1154ba695078d29ea6c4e1adb55c463959cd77509adf09710e2315827d66271a",
    "sha256:528c8710fd95f61d40b8bb8a549fa8dfa737d9b9c7c7b2ae55f745c972dddacd",
    "sha256:37ee47034d9b78f10f0c5ce3a25e6b6e58997fcadaf5f896c603a10c5f35fb31",
    "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
    "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
    "sha256:b75c0703b86b8ccbdc1f1b28b4982774768861ac250f83bdb940b1e90291f302",
    "sha256:5c121779bb29172c628a21087ea8ced766959da2f223c8b6bd4ffe943ace43d8",
    "sha256:3ee91c5cb95b01496b4afdc721ba7fd3c22e0e5e2f3e9e70d3f8579b5082d4f3",
    "sha256:6bbb1d0f845289217e20b66697fa7d651394d89983b0f5a89b88f037194476fe",
    "sha256:b44b0832d4c6bf33122ce3aa896b133df88275e6d20663a9bf2d941f764ac1fd",
    "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
    "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
    "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
    ]
    }

    可见training/webapp镜像总共由 13 层只读层镜像构成,这个和 $ docker history training/webapp 输出的结果是吻合

  • 那么从当前容器web31的角度,AUFS 的结构情况是怎样的呢?

    • 查看宿主机 AUFS 的文件结构

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      root@ubuntu:/var/lib/docker/aufs/diff# ls -lt
      total 60
      drwxr-xr-x 4 root root 4096 Dec 19 16:25 5420c2ad6952b5597042f7e3ca75e61333e8bda52eb4b9b0a197c4e4c5547c9e
      drwxr-xr-x 6 root root 4096 Dec 19 16:25 5420c2ad6952b5597042f7e3ca75e61333e8bda52eb4b9b0a197c4e4c5547c9e-init
      drwxr-xr-x 2 root root 4096 Dec 19 16:25 828a1c91a6fb1928559b7b9813c0917affd84fcfa7a4e79476d20623b2c29c2d
      drwxr-xr-x 2 root root 4096 Dec 19 16:25 8d8fd100b49edd233212e17c64c8b5061c2b79eb7f7f2fd5fae36c9bf59a502f
      drwxr-xr-x 2 root root 4096 Dec 19 16:25 9b79d3f46e7826defa1c283d8282f3169c876bde8b6084cdbe60672acacb9274
      drwxr-xr-x 3 root root 4096 Dec 19 16:25 864df82537caf88937c58efbf158f9185ebb872cfb54b15d8888f33561ddaa56
      drwxr-xr-x 3 root root 4096 Dec 19 16:25 a3c07d88c61c220d3cc2e2b317b317dec0be11fd629eab7bd3def680a25686cb
      drwxr-xr-x 3 root root 4096 Dec 19 16:25 e31f34199774f4446ddde561a3e1a3dbbc254e483f1bd7193571b93f776becc4
      drwxr-xr-x 6 root root 4096 Dec 19 16:25 1640c122bc62e1fa893cdeae766952951a934864dacbef3e87d2d9eae68c78d1
      drwxr-xr-x 3 root root 4096 Dec 19 16:24 258cfd490a2345067156a2f43d9425e7d12907ce3df64072e37a17ab18b55248
      drwxr-xr-x 2 root root 4096 Dec 19 16:24 67614ba4f62bb6f949acff511a18447a620d5b0a2c4c293bdeb7cd9e97a6cdbc
      drwxr-xr-x 2 root root 4096 Dec 19 16:24 654940ca942ba450e2c5dd38e10bc462333a0307b8531e3193b9f9cbcb119d16
      drwxr-xr-x 3 root root 4096 Dec 19 16:24 37edd74902c396df578b8fcfd233457fe27efd3e0f871e677ada43a92f0bad79
      drwxr-xr-x 6 root root 4096 Dec 19 16:24 9c0b2e0c1996496f8031c7bf148940e55b34bf7efa067725453430c8db3a27ea
      drwxr-xr-x 21 root root 4096 Dec 19 16:24 5ae0f9c8801e4493a1b5c6a2ba07bf4502e63193603f50681aa07fa5cf992949

      可以看到,容器需要使用的镜像总共有 15 层,当前容器使用的镜像比training/webapp的初始镜像多了两层,那么这 15 层镜像(目录)在当前容器中是如何对应的呢?

    • 查看 Docker 容器中针对 AUFS 文件系统的使用情况
      进入 docker 的命令行,在 /sys/fs/aufs/si_<CONTAINERID> 中查看各级镜像权限对应情况;

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      root@ubuntu: docker run -it training/webapp /bin/bash
      root@762be790cc1f:/opt/webapp# cd /sys/fs/aufs/si_d37f4010e9a078ff/
      root@762be790cc1f:/sys/fs/aufs/si_d37f4010e9a078ff# ls
      br0 br10 br12 br14 br3 br5 br7 br9 brid1 brid11 brid13 brid2 brid4 brid6 brid8 xi_path
      br1 br11 br13 br2 br4 br6 br8 brid0 brid10 brid12 brid14 brid3 brid5 brid7 brid9
      root@762be790cc1f:/sys/fs/aufs/si_d37f4010e9a078ff# cat *
      /var/lib/docker/aufs/diff/8a94a9d1a72928628004cb344f92a54b5325f44a10a54eeb83bc0d79bfed3d2f=rw
      /var/lib/docker/aufs/diff/8a94a9d1a72928628004cb344f92a54b5325f44a10a54eeb83bc0d79bfed3d2f-init=ro+wh # 该层以及以下的13层都是只读镜像
      /var/lib/docker/aufs/diff/67614ba4f62bb6f949acff511a18447a620d5b0a2c4c293bdeb7cd9e97a6cdbc=ro+wh
      /var/lib/docker/aufs/diff/654940ca942ba450e2c5dd38e10bc462333a0307b8531e3193b9f9cbcb119d16=ro+wh
      /var/lib/docker/aufs/diff/37edd74902c396df578b8fcfd233457fe27efd3e0f871e677ada43a92f0bad79=ro+wh
      /var/lib/docker/aufs/diff/9c0b2e0c1996496f8031c7bf148940e55b34bf7efa067725453430c8db3a27ea=ro+wh
      /var/lib/docker/aufs/diff/5ae0f9c8801e4493a1b5c6a2ba07bf4502e63193603f50681aa07fa5cf992949=ro+wh
      /var/lib/docker/aufs/diff/828a1c91a6fb1928559b7b9813c0917affd84fcfa7a4e79476d20623b2c29c2d=ro+wh
      /var/lib/docker/aufs/diff/8d8fd100b49edd233212e17c64c8b5061c2b79eb7f7f2fd5fae36c9bf59a502f=ro+wh
      /var/lib/docker/aufs/diff/9b79d3f46e7826defa1c283d8282f3169c876bde8b6084cdbe60672acacb9274=ro+wh
      /var/lib/docker/aufs/diff/864df82537caf88937c58efbf158f9185ebb872cfb54b15d8888f33561ddaa56=ro+wh
      /var/lib/docker/aufs/diff/a3c07d88c61c220d3cc2e2b317b317dec0be11fd629eab7bd3def680a25686cb=ro+wh
      /var/lib/docker/aufs/diff/e31f34199774f4446ddde561a3e1a3dbbc254e483f1bd7193571b93f776becc4=ro+wh
      /var/lib/docker/aufs/diff/1640c122bc62e1fa893cdeae766952951a934864dacbef3e87d2d9eae68c78d1=ro+wh
      /var/lib/docker/aufs/diff/258cfd490a2345067156a2f43d9425e7d12907ce3df64072e37a17ab18b55248=ro+wh
      64
      65
      74
      75
      76
      77
      78
      66
      67
      68
      69
      70
      71
      72
      73
      /dev/shm/aufs.xino

      可见,比起该容器的初始镜像,容器多了两层镜像,
      /var/lib/docker/aufs/diff/8a94a9d1a72928628004cb344f92a54b5325f44a10a54eeb83bc0d79bfed3d2f=rw
      /var/lib/docker/aufs/diff/8a94a9d1a72928628004cb344f92a54b5325f44a10a54eeb83bc0d79bfed3d2f-init=ro+wh
      根据已有的13层镜像创建一层新的只读镜像 8a94a9d1a72928628004cb344f92a54b5325f44a10a54eeb83bc0d79bfed3d2f-init,然后再创建一层可读写镜像层 8a94a9d1a72928628004cb344f92a54b5325f44a10a54eeb83bc0d79bfed3d2f,然后所有在容器内发生的改动,均保存到该层中。

      如上,反映了 Docker 的镜像和容器的镜像层次结构,容器的镜像层次结构主要是多了一层可读写的镜像层,使 Docker 容器可以进行读写操作;但要注意的是,Docker 容器对改动的保存是临时的,当 Docker 关闭以后,所有的修改也会随之删除。要能够永久的保留这些修改,有两种选择,1、使用docker commit命令将当前容器中发生的变更生成一个新的只读镜像;2、使用 Data Volume。

做一些试验

  • 在容器中创建一个文件,该文件会被创建在可写的容器层中

    • 进入 Docker command,创建一个文件 helloworld

      1
      2
      3
      4
      root@ubuntu:~# docker run -it training/webapp /bin/bash
      root@832f3494ce20:/opt# cd ~
      root@832f3494ce20:~# touch helloworld
      root@832f3494ce20:~# echo "hello world" > helloworld
    • 在宿主机上查看 AUFS 文件系统的变化

      1
      2
      3
      4
      5
      6
      7
      8
      root@ubuntu:~# cd /var/lib/docker/aufs/diff
      root@ubuntu:/var/lib/docker/aufs/diff# find -iname helloworld
      ./a24e1296a1ecce3e8c2a6f2bc5bee83512b05cea70939d536f91b7ba089f7d1c/root/helloworld
      root@ubuntu:/var/lib/docker/aufs/diff# ls -lt
      total 84
      drwxr-xr-x 5 root root 4096 Dec 20 08:14 a24e1296a1ecce3e8c2a6f2bc5bee83512b05cea70939d536f91b7ba089f7d1c
      drwxr-xr-x 6 root root 4096 Dec 20 08:13 a24e1296a1ecce3e8c2a6f2bc5bee83512b05cea70939d536f91b7ba089f7d1c-init
      drwxr-xr-x 4 root root 4096 Dec 20 08:12 693983a5a21e6225d3dcfc1976b9a97a8e73e66f44e9e8c143b492f393eb040d

      可见,在 docker 中生成的 helloworld 文件,保存在 a24e1296a1ecce3e8c2a6f2bc5bee83512b05cea70939d536f91b7ba089f7d1c 目录中,这正是 Docker 容器的可写层。

  • 修改一个镜像层中的文件

    • 在 Docker 中,对 source.list 进行修改

      1
      root@832f3494ce20:/sys/fs/aufs/si_1dcd197dfd656845# vim /etc/apt/sources.list

      这里,这是简单的将某一行进行注释,下面我们来看看宿主机上 AUFS 的文件的变化情况

    • 在宿主机上,我们来看看变化情况
      修改之前

      1
      2
      3
      4
      root@ubuntu:/var/lib/docker/aufs/diff# find -iname sources.list
      ./37edd74902c396df578b8fcfd233457fe27efd3e0f871e677ada43a92f0bad79/etc/apt/sources.list
      ./5ae0f9c8801e4493a1b5c6a2ba07bf4502e63193603f50681aa07fa5cf992949/usr/share/doc/apt/examples/sources.list
      ./5ae0f9c8801e4493a1b5c6a2ba07bf4502e63193603f50681aa07fa5cf992949/etc/apt/sources.list

      修改之后

      1
      2
      3
      4
      5
      root@ubuntu:/var/lib/docker/aufs/diff# find -iname sources.list
      ./37edd74902c396df578b8fcfd233457fe27efd3e0f871e677ada43a92f0bad79/etc/apt/sources.list
      ./a24e1296a1ecce3e8c2a6f2bc5bee83512b05cea70939d536f91b7ba089f7d1c/etc/apt/sources.list
      ./5ae0f9c8801e4493a1b5c6a2ba07bf4502e63193603f50681aa07fa5cf992949/usr/share/doc/apt/examples/sources.list
      ./5ae0f9c8801e4493a1b5c6a2ba07bf4502e63193603f50681aa07fa5cf992949/etc/apt/sources.list

      我们可以清楚的看到,发生变化的 source.list 被添加到了科写层a24e1296a1ecce3e8c2a6f2bc5bee83512b05cea70939d536f91b7ba089f7d1c

  • 删除容器层中的文件
    我们来试图在容器中删除 itsdangerous.py,看看 AUFS 文件系统发生了什么变化

    • 在容器中删除

      1
      2
      3
      4
      5
      6
      root@832f3494ce20:/sys/fs/aufs/si_1dcd197dfd656845# cd /
      root@832f3494ce20:/# find -iname itsdangerous.py
      ./usr/local/lib/python2.7/dist-packages/itsdangerous.py
      root@832f3494ce20:/# rm ./usr/local/lib/python2.7/dist-packages/itsdangerous.py
      root@832f3494ce20:/# find -iname itsdangerous.py
      root@832f3494ce20:/#
    • 在宿主机上查看 AUFS 文件系统的变化情况

      1
      2
      3
      root@ubuntu:/var/lib/docker/aufs/diff# find -iname *itsdangerous.py
      ./a24e1296a1ecce3e8c2a6f2bc5bee83512b05cea70939d536f91b7ba089f7d1c/usr/local/lib/python2.7/dist-packages/.wh.itsdangerous.py
      ./a3c07d88c61c220d3cc2e2b317b317dec0be11fd629eab7bd3def680a25686cb/usr/local/lib/python2.7/dist-packages/itsdangerous.py

      可见,容器层(既 AUFS 可写层) a24e1296a1ecce3e8c2a6f2bc5bee83512b05cea70939d536f91b7ba089f7d1c只是相应的生成了一个Whiteout 文件既是.wh.+文件名,让其在容器中不可见,而镜像层的文件不会发生任何变化。

    • 在宿主机上直接将 .wh 文件删除,itsdangerous.py 又出现在了容器中
      在宿主机上删除 .wh 文件

      1
      root@ubuntu:/var/lib/docker/aufs/diff# rm ./a24e1296a1ecce3e8c2a6f2bc5bee83512b05cea70939d536f91b7ba089f7d1c/usr/local/lib/python2.7/dist-packages/.wh.itsdangerous.py

      检查容器

      1
      2
      root@832f3494ce20:/# find -iname itsdangerous.py
      ./usr/local/lib/python2.7/dist-packages/itsdangerous.py

      有意思,itsdangerous.py 在容器中又恢复了.. 这就是 AUFS 的特性,被删除的文件只是在容器层中通过 .wh 文件加上了一个不可见的标识。