为了更好的使用storage driver,最好首先了解Docker如何构建,如何存储images,镜像如何被container使用。

Images和Layers

Docker镜像是通过一组layer构建的

FROM ubuntu:15.04
COPY . /app
RUN make /app
CMD python /app/app.py

上面的Dockerfile由4个命令构成,每个都会创建一个layer,而me层layer都是与之前layer的不同。

Contianer & Layer

多个容器共享Ubuntu 15.04镜像

Container Size

如果要大致查看容器的大小,可以

docker ps -s

其中,size表示每个容器writable layer的数据量。

virtual size表示size加上read-only镜像的数据量。

docker镜像

当使用docker pull 命令拉取镜像是,通常会存储在/var/lib/docker/

$ docker pull ubuntu:15.04

15.04: Pulling from library/ubuntu
1ba8ac955b97: Pull complete
f157c4e5ede7: Pull complete
0b7e98f84c4c: Pull complete
a3ed95caeb02: Pull complete
Digest: sha256:5e279a9df07990286cce22e1b0f5b0490629ca6d187698746ae5e28e604a640e
Status: Downloaded newer image for ubuntu:15.04

每层layer会存放在Docker host的本地存储区域的专有目录,比如/var/lib/docker/<storage-driver>/layers/

比如,默认的storage driver使用aufs

$ ls /var/lib/docker/aufs/layers
1d6674ff835b10f76e354806e16b950f91a191d3b471236609ab13a930275e24
5dbb0cbe0148cf447b9464a358c1587be586058d9a4c9ce079320265e2bb94e7
bef7199f2ed8e86fa4ada1309cfad3089e0542fec8894690529e4c04a7ca2d73
ebf814eccfe98f2704660ca1d844e4348db3b5ccc637eb905d4818fbfb00a06a

假设,有两个不同的Dockerfile,创建镜像acme/my-base-image:1.0

FROM ubuntu:16.10
COPY . /app

第2个镜像基于acme/my-base-image:1.0 ,添加新的layer

FROM acme/my-base-image:1.0
CMD /app/hello.sh

第2个镜像将包含第1个镜像的所有layers,同时包括新添加的layer。

首先,创建cow-test/目录,并进入该目录。在该目录创建hello.sh

#!/bin/sh
echo "Hello world"

修改hello.sh为执行权限

chmod +x hello.sh

将第1个Dockerfile的内容复制到Dockerfile.bas,将第2个Dockerfile内容复制到新的Dockerfile文件。

cow-test/ 目录构建第1个镜像

$ docker build -t acme/my-base-image:1.0 -f Dockerfile.base .

Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM ubuntu:16.10
 ---> 31005225a745
Step 2/2 : COPY . /app
 ---> Using cache
 ---> bd09118bcef6
Successfully built bd09118bcef6
Successfully tagged acme/my-base-image:1.0

构建第2个镜像

$ docker build -t acme/my-final-image:1.0 -f Dockerfile .

Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM acme/my-base-image:1.0
 ---> bd09118bcef6
Step 2/2 : CMD /app/hello.sh
 ---> Running in a07b694759ba
 ---> dbf995fc07ff
Removing intermediate container a07b694759ba
Successfully built dbf995fc07ff
Successfully tagged acme/my-final-image:1.0

查看镜像

$ docker image ls

REPOSITORY                         TAG                     IMAGE ID            CREATED             SIZE
acme/my-final-image                1.0                     dbf995fc07ff        58 seconds ago      103MB
acme/my-base-image                 1.0                     bd09118bcef6        3 minutes ago       103MB

查看镜像每个layer的构成

$ docker history bd09118bcef6
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
bd09118bcef6        4 minutes ago       /bin/sh -c #(nop) COPY dir:35a7eb158c1504e...   100B                
31005225a745        3 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           3 months ago        /bin/sh -c mkdir -p /run/systemd && echo '...   7B                  
<missing>           3 months ago        /bin/sh -c sed -i 's/^#\s*\(deb.*universe\...   2.78kB              
<missing>           3 months ago        /bin/sh -c rm -rf /var/lib/apt/lists/*          0B                  
<missing>           3 months ago        /bin/sh -c set -xe   && echo '#!/bin/sh' >...   745B                
<missing>           3 months ago        /bin/sh -c #(nop) ADD file:eef57983bd66e3a...   103MB
$ docker history dbf995fc07ff

IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
dbf995fc07ff        3 minutes ago       /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/a...   0B                  
bd09118bcef6        5 minutes ago       /bin/sh -c #(nop) COPY dir:35a7eb158c1504e...   100B                
31005225a745        3 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B                  
<missing>           3 months ago        /bin/sh -c mkdir -p /run/systemd && echo '...   7B                  
<missing>           3 months ago        /bin/sh -c sed -i 's/^#\s*\(deb.*universe\...   2.78kB              
<missing>           3 months ago        /bin/sh -c rm -rf /var/lib/apt/lists/*          0B                  
<missing>           3 months ago        /bin/sh -c set -xe   && echo '#!/bin/sh' >...   745B                
<missing>           3 months ago        /bin/sh -c #(nop) ADD file:eef57983bd66e3a...   103MB

由上可知,除了第2个镜像的top layer不同之外,其他layer会在两个镜像间共享,但只会在/var/lib/docker 保存一次。

而top layer并不会占用空间,因为它不会更改任何文件,而只是运行命令。

docker history中的<missing>行,表示layer是在其他system构建,而在本地不可获取。

copy-on-write

当启动容器时,会在其他layer的顶层增加可写的container layer。当容器中的文件修改时,storage driver会执行copy-on-write操作,对于aufs、overlay、overlay2,copy-on-write操作的过程大致是:

  • 在image layers搜索文件,当搜索到之后,它会加入cache

  • 当发现file的第一个copy时,执行copy_up 操作,将其拷贝到容器layer

  • 任何对文件的修改都是对文件副本的修改。

Btrfs,ZFS和其他driver在处理copy-on-write时并不相同。

对于write-heavey的应用,不应该在container存储数据,而是使用Docker volumes。

启动多个容器

$ docker run -dit --name my_container_1 acme/my-final-image:1.0 bash \
  && docker run -dit --name my_container_2 acme/my-final-image:1.0 bash \
  && docker run -dit --name my_container_3 acme/my-final-image:1.0 bash \
  && docker run -dit --name my_container_4 acme/my-final-image:1.0 bash \
  && docker run -dit --name my_container_5 acme/my-final-image:1.0 bash

  c36785c423ec7e0422b2af7364a7ba4da6146cbba7981a0951fcc3fa0430c409
  dcad7101795e4206e637d9358a818e5c32e13b349e62b00bf05cd5a4343ea513
  1e7264576d78a3134fbaf7829bc24b1d96017cf2bc046b7cd8b08b5775c33d0c
  38fa94212a419a082e6a6b87a8e2ec4a44dd327d7069b85892a707e3fc818544
  1a174fc216cccf18ec7d4fe14e008e30130b11ede0f0f94a87982e310cf2e765

查看运行的容器

CONTAINER ID      IMAGE                     COMMAND     CREATED              STATUS              PORTS      NAMES
1a174fc216cc      acme/my-final-image:1.0   "bash"      About a minute ago   Up About a minute              my_container_5
38fa94212a41      acme/my-final-image:1.0   "bash"      About a minute ago   Up About a minute              my_container_4
1e7264576d78      acme/my-final-image:1.0   "bash"      About a minute ago   Up About a minute              my_container_3
dcad7101795e      acme/my-final-image:1.0   "bash"      About a minute ago   Up About a minute              my_container_2
c36785c423ec      acme/my-final-image:1.0   "bash"      About a minute ago   Up About a minute              my_container_1

local storage的列表

$ sudo ls /var/lib/docker/containers

1a174fc216cccf18ec7d4fe14e008e30130b11ede0f0f94a87982e310cf2e765
1e7264576d78a3134fbaf7829bc24b1d96017cf2bc046b7cd8b08b5775c33d0c
38fa94212a419a082e6a6b87a8e2ec4a44dd327d7069b85892a707e3fc818544
c36785c423ec7e0422b2af7364a7ba4da6146cbba7981a0951fcc3fa0430c409
dcad7101795e4206e637d9358a818e5c32e13b349e62b00bf05cd5a4343ea513

容器的大小

$ sudo du -sh /var/lib/docker/containers/*

32K  /var/lib/docker/containers/1a174fc216cccf18ec7d4fe14e008e30130b11ede0f0f94a87982e310cf2e765
32K  /var/lib/docker/containers/1e7264576d78a3134fbaf7829bc24b1d96017cf2bc046b7cd8b08b5775c33d0c
32K  /var/lib/docker/containers/38fa94212a419a082e6a6b87a8e2ec4a44dd327d7069b85892a707e3fc818544
32K  /var/lib/docker/containers/c36785c423ec7e0422b2af7364a7ba4da6146cbba7981a0951fcc3fa0430c409
32K  /var/lib/docker/containers/dcad7101795e4206e637d9358a818e5c32e13b349e62b00bf05cd5a4343ea513

results matching ""

    No results matching ""