1. 程式人生 > 實用技巧 >【Docker】關於儲存驅動

【Docker】關於儲存驅動

參考教程:https://docs.docker.com/storage/storagedriver/
以下內容來自官方文件翻譯

環境

  1. virtual box 6.1
  2. centos 7.8
  3. docker 19.03

To use storage drivers effectively, it’s important to know how Docker builds and stores images, and how these images are used by containers. You can use this information to make informed choices about the best way to persist data from your applications and avoid performance problems along the way.

為了高效地使用儲存驅動,瞭解 Docker 如何生成和儲存映象以及容器如何使用這些映象非常重要。您可以使用此資訊來做出明智的選擇,並以最佳方式儲存應用程式中的資料,避免使用過程中的效能問題。

Storage drivers allow you to create data in the writable layer of your container. The files won’t be persisted after the container is deleted, and both read and write speeds are lower than native file system performance.

儲存驅動允許您在容器的可寫層中建立資料。刪除容器後,檔案不會保留,讀取和寫入速度都低於本機檔案系統性能。

Note: Operations that are known to be problematic include write-intensive database storage, particularly when pre-existing data exists in the read-only layer. More details are provided in this document.

注意:已知有問題的操作包括密集型寫入資料庫儲存,特別是當預先存在的資料存在於只讀層中時。本文件提供了更多詳細資訊。

映象和層

A Docker image is built up from a series of layers. Each layer represents an instruction in the image’s Dockerfile. Each layer except the very last one is read-only. Consider the following Dockerfile:

Docker 映象由一系列圖層構建。每一層表示映象的 Dockerfile 中的指令。除了最後一個圖層之外,每個圖層都是隻讀的。請考慮以下 Dockerfile:

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

This Dockerfile contains four commands, each of which creates a layer. The FROM statement starts out by creating a layer from the ubuntu:18.04 image. The COPY command adds some files from your Docker client’s current directory. The RUN command builds your application using the make command. Finally, the last layer specifies what command to run within the container.

此 Dockerfile 包含四個命令,每個命令建立一個圖層。FROM 語句根據映象 ubuntu:18.04 建立一層。COPY 命令從 Docker 客戶端的當前目錄中新增一些檔案。RUN 命令使用 make 命令生成應用程式。最後,最後一層指定要在容器中執行的命令。

Each layer is only a set of differences from the layer before it. The layers are stacked on top of each other. When you create a new container, you add a new writable layer on top of the underlying layers. This layer is often called the “container layer”. All changes made to the running container, such as writing new files, modifying existing files, and deleting files, are written to this thin writable container layer. The diagram below shows a container based on the Ubuntu 15.04 image.

每一層只是與上一層不同的集合。這些層彼此堆疊。建立新容器時,在基礎層之上新增新的可寫層。該層通常稱為“容器層”。對執行中的容器所做的所有更改(例如寫入新檔案,修改現有檔案和刪除檔案)都將寫入很薄的可寫容器層。下圖顯示了基於 Ubuntu 15.04 映象的容器。

A storage driver handles the details about the way these layers interact with each other. Different storage drivers are available, which have advantages and disadvantages in different situations.

儲存驅動處理有關這些層相互互動的方式的詳細資訊。Docker 提供了不同的儲存驅動,它們在不同情況下各有利弊。

容器和層

The major difference between a container and an image is the top writable layer. All writes to the container that add new or modify existing data are stored in this writable layer. When the container is deleted, the writable layer is also deleted. The underlying image remains unchanged.

容器和映象之間的主要區別是可寫頂層。在容器中新增新資料或修改現有資料的所有寫操作都儲存在此可寫層中。刪除容器後,可寫層也會被刪除。基礎映象保持不變。

Because each container has its own writable container layer, and all changes are stored in this container layer, multiple containers can share access to the same underlying image and yet have their own data state. The diagram below shows multiple containers sharing the same Ubuntu 15.04 image.

因為每個容器都有其自己的可寫容器層,並且所有更改都儲存在該容器層中,所以多個容器可以共享對同一基礎映象的訪問,但具有自己的資料狀態。下圖顯示了共享同一 Ubuntu 15.04 映象的多個容器。

Note: If you need multiple images to have shared access to the exact same data, store this data in a Docker volume and mount it into your containers.

注意:如果您需要多個映象來共享對完全相同的資料的訪問許可權,請將該資料儲存在 Docker 資料卷中並將其掛載到您的容器中。

Docker uses storage drivers to manage the contents of the image layers and the writable container layer. Each storage driver handles the implementation differently, but all drivers use stackable image layers and the copy-on-write (CoW) strategy.

Docker 使用儲存驅動來管理映象層和可寫容器層的內容。每個儲存驅動對實現的處理方式不同,但是所有驅動都使用可堆疊的映象層和寫時複製(CoW)策略。

容器在磁碟上的大小

To view the approximate size of a running container, you can use the docker ps -s command. Two different columns relate to size.

要檢視正在執行的容器的大致大小,可以使用 docker ps -s 命令。有兩個不同的列與大小有關。

  • size: the amount of data (on disk) that is used for the writable layer of each container.

  • size:每個容器的可寫層使用的資料量(磁碟上)。

  • virtual size: the amount of data used for the read-only image data used by the container plus the container’s writable layer size. Multiple containers may share some or all read-only image data. Two containers started from the same image share 100% of the read-only data, while two containers with different images which have layers in common share those common layers. Therefore, you can’t just total the virtual sizes. This over-estimates the total disk usage by a potentially non-trivial amount.

  • virtual size:容器使用的用於只讀映象資料的資料量加上容器的可寫層大小。多個容器可以共享部分或全部只讀映象資料。從同一映象啟動的兩個容器共享 100% 的只讀資料,而具有不同映象的兩個容器(具有相同的層)則共享這些公共層。因此,您不能僅僅計算虛擬大小。這高估了總磁碟使用量,可能是一筆不小的數量。

The total disk space used by all of the running containers on disk is some combination of each container’s size and the virtual size values. If multiple containers started from the same exact image, the total size on disk for these containers would be SUM (size of containers) plus one image size (virtual size- size).

磁碟上所有正在執行的容器使用的磁碟總空間是每個容器的大小和虛擬大小值的某種組合。如果多個容器從相同的精確映象啟動,則這些容器在磁碟上的總大小將為SUM(容器大小)加上一個映象大小(虛擬大小-大小)。

[root@master ~]# docker ps -s
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES               SIZE
5d1021ee8b24        nginx:alpine        "/docker-entrypoint.…"   2 weeks ago         Up 3 seconds        0.0.0.0:8080->80/tcp    goofy_mendel        1.12kB (virtual 21.8MB)
497d0139b307        nginx:alpine        "/docker-entrypoint.…"   3 weeks ago         Up 4 minutes        0.0.0.0:32768->80/tcp   web                 1.12kB (virtual 21.8MB)

總的大小:total = 1.12kB * 2 + 21.8MB - 1.12KB

This also does not count the following additional ways a container can take up disk space:

這不包括容器可以佔用磁碟空間的以下其他方式:

  • Disk space used for log files if you use the json-file logging driver. This can be non-trivial if your container generates a large amount of logging data and log rotation is not configured.

  • Volumes and bind mounts used by the container.

  • Disk space used for the container’s configuration files, which are typically small.

  • Memory written to disk (if swapping is enabled).

  • Checkpoints, if you’re using the experimental checkpoint/restore feature.

  • 如果使用 json 檔案日誌記錄驅動,則用於日誌檔案的磁碟空間。如果您的容器生成大量的日誌資料並且未配置日誌滾動,那麼這可能有較大影響。

  • 容器使用的卷和繫結掛載。

  • 容器的配置檔案所用的磁碟空間,通常較小。

  • 記憶體寫入磁碟(如果啟用了交換)。

  • 檢查點(如果您正在使用實驗性檢查點/恢復功能)。

寫時複製(CoW)策略

Copy-on-write is a strategy of sharing and copying files for maximum efficiency. If a file or directory exists in a lower layer within the image, and another layer (including the writable layer) needs read access to it, it just uses the existing file. The first time another layer needs to modify the file (when building the image or running the container), the file is copied into that layer and modified. This minimizes I/O and the size of each of the subsequent layers. These advantages are explained in more depth below.

寫入時複製是一種共享和複製檔案的策略,可最大程度地提高效率。 如果檔案或目錄位於映象的較低層中,而另一層(包括可寫層)需要對其進行讀取訪問,則它僅使用現有檔案。另一層第一次需要修改檔案時(在構建映象或執行容器時),檔案被複制到該層並進行修改。 這樣可以將 I/O 和每個後續層的大小最小化。這些優點將在下面更深入地說明。

共享減小映象

When you use docker pull to pull down an image from a repository, or when you create a container from an image that does not yet exist locally, each layer is pulled down separately, and stored in Docker’s local storage area, which is usually /var/lib/docker/ on Linux hosts. You can see these layers being pulled in this example:

當您使用 docker pull 來從儲存庫中拉取映象時,或者當您從本地尚不存在的映象中建立容器時,每一層都會被分別拉取,並存儲在 Docker 的本地儲存區域中,通常在 Linux 主機上的 /var/lib/docker/。 您可以在此示例中看到這些層被拉取:

[root@master ~]# docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
171857c49d0f: Pull complete
419640447d26: Pull complete
61e52f862619: Pull complete
Digest: sha256:646942475da61b4ce9cc5b3fadb42642ea90e5d0de46111458e100ff2c7031e6
Status: Downloaded newer image for ubuntu:18.04
docker.io/library/ubuntu:18.04
[root@master ~]#

Each of these layers is stored in its own directory inside the Docker host’s local storage area. To examine the layers on the filesystem, list the contents of /var/lib/docker/<storage-driver>. This example uses the overlay2 storage driver:

所有這些層都儲存在 Docker 主機本地儲存區域內的自己的目錄中。要檢查檔案系統上的各層,請列出/var/lib/docker/<storage-driver>的內容。 此示例使用overlay2儲存驅動程式:

[root@master ~]#  ls /var/lib/docker/overlay2
07e2e128dd90a580133c0a3d01dd5cd9a160ece95c984b573b7b7758e0087a89       6f64ae41f33cfd00f26912f8b0c6f9c2a9008dfb0f2339e2a2c7246a056265e6
0b4382e9fba66c5a9b929af53dd33bab06b5ca5176acbba99f02fa15e23bb3d5       737c8cd71c0f7ead61038d43fd211760ae0e0d923587ebf913a6ce55925b9062
0dc6887647a656e49928e0c46291aff65f6c6d4900da139e6a3dce850493fed2       7aa8c39a5eea25bd9ac0950739f2e2d3e2c51bd5451941fbc525201ede4f4eb7
119250987b77acf7e4457080cdad03d3e4c96988b3cc952366d4320a44fb1f8e       8f49a8351ade76bcd02a5cd43833da1ce729ddc9a88ed593fcc8eacf1d9b530f
232fd1b5e48a094fbe94092ac8490ce3edc9afe9e9f91c1018b865b8ecf158dc       9457afb88f8b5f78cd1fc7c63ce8a81bfb4c37ac728ded3a788c87fd9badbd1a
250eb9dd5f52a851b2bf18aa3807acf4c94391c7ed86d9825d57c0fe52a469bd       a9c71bbbbf73132eeb66999122da1ab3fd1579cf128a8c5d517a67ff68e9d21f
2b31f3992eef94b3c3ea540f1df2753e2ee279c5a9b0caaa6195199b0ea0c5dc       backingFsBlockDev
347ea1b6dd30ce456cf1f99fdd93954bdbf3fcbe22337894d0016beaaa6cea37       c7ebdb0ed63bffac4e3a57212e5995e28c52961ac134c43008ef0909382122df
36fadfc8166fbf2316da5ec7efc76f94505fa9974be858b370ae176a03f9d3f5       cb9877985988bc257bb64a96d220ec09b90ed5ea9e5e8d32dabbbe3a6952b669
48729098b14376a78a821e052e2f4c8261ce26b4ae7e2ebad2e723118ca64234       daa81cc2507e2878a838cfb8ec0cc9c54c46cf08d1f791565c91d3ca5bd0a92a
4aa0e717b19de7679450c65d8f7ef23b2d7116c81ca3a5fb89eafb9abcc4039e       e2eddfed55a6bc8663ce4878376dd039607f61b99efedf8745f7d2b33a1e7112
51b36c1db9f9c2d0158da34e3397d783d6d23166a96c1a03c07e02606e544273       e3c64c744ea35a5079dd0c08058c5f26ac90c0661811be8ecb64f857424120d2
51f87163f04d9f5f50a394872918491bfbe03841c5ce35ac0d8e56931cef47b4       eacfdaab2b8295f696e9c1fc0eb99bc488a1261d82a231e3f51d529a7cd6cdf3
5238cfaa817004531c6b52aca024bc141fd8a642e862fc3cd6e96538b6eb9e04       ec0e3ae382bac3b09c95d9d362d84849ca3ea70fd49f4b55884cc0976101d098
5a9a2dcb90abc50c286c0e4eac8d75c37267b3459af079ccf35a08989acae96c       f343ddba472c672753911e20b1f12b04eba797e32210988f84c3204d7218c2f0
5a9a2dcb90abc50c286c0e4eac8d75c37267b3459af079ccf35a08989acae96c-init  f343ddba472c672753911e20b1f12b04eba797e32210988f84c3204d7218c2f0-init
6d1ffd3b06a9b0a36d791dba90bb7f4d9885742163e6ae4ba45d35fba0216d27       f45ba8e0f94a2b16bd7eadf3110d4365392301bcaa9ca8fd38624803c8378982
6d1ffd3b06a9b0a36d791dba90bb7f4d9885742163e6ae4ba45d35fba0216d27-init  f45ba8e0f94a2b16bd7eadf3110d4365392301bcaa9ca8fd38624803c8378982-init
6ebbaef61ac09511197ab4d1cf6159ba63f9aff2850b74fe7d3c1a1587f27d11       fb5cd37f0436f42ca1fb23e7cea2f11286241bb1311a367e6a2e54df0973728c
6f5e73a855f5517ce47ccd43a26da54ff25f899d9d0c64f7792197aeaa78b052       l
[root@master ~]#

The directory names do not correspond to the layer IDs (this has been true since Docker 1.10).

目錄名稱與層ID不對應(自 Docker 1.10 開始就是如此)。

Now imagine that you have two different Dockerfiles. You use the first one to create an image called acme/my-base-image:1.0.

現在,假設您有兩個不同的 Dockerfile。您使用第一個建立一個名為 acme/my-base-image:1.0 的映象。

FROM ubuntu:18.04
COPY . /app

The second one is based on acme/my-base-image:1.0, but has some additional layers:

第二個基於acme/my-base-image:1.0,但有一些額外層:

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

The second image contains all the layers from the first image, plus a new layer with the CMD instruction, and a read-write container layer. Docker already has all the layers from the first image, so it does not need to pull them again. The two images share any layers they have in common.

第二個映象包含第一個映象中的所有層,再加上帶有“CMD”指令的新層,以及一個可讀寫容器層。Docker 已經具有第一個映象中的所有層,因此不需要再次將其拉取。這兩個映象共享它們共有的任何圖層。

If you build images from the two Dockerfiles, you can use docker image ls and docker history commands to verify that the cryptographic IDs of the shared layers are the same.

如果您從兩個Dockerfile中構建映象,則可以使用 docker image lsdocker history 命令來驗證共享層的 ID 是否相同。

[root@master ~]# mkdir cow-test
[root@master ~]# ls
anaconda-ks.cfg  cow-test  docker  html  nvm  software
[root@master ~]# cd cow-test/
[root@master cow-test]# vim hello.sh
[root@master cow-test]# cat hello.sh
#!/bin/sh
echo "Hello world"
[root@master cow-test]# chmod +x hello.sh
[root@master cow-test]# ls
hello.sh
[root@master cow-test]# vim Dockerfile.base
[root@master cow-test]# vim Dockerfile
[root@master cow-test]# 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:18.04
 ---> 56def654ec22
Step 2/2 : COPY . /app
 ---> 72ee914ed695
Successfully built 72ee914ed695
Successfully tagged acme/my-base-image:1.0
[root@master cow-test]# 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
 ---> 72ee914ed695
Step 2/2 : CMD /app/hello.sh
 ---> Running in 36111dcae4b4
Removing intermediate container 36111dcae4b4
 ---> 0f8b98bb868d
Successfully built 0f8b98bb868d
Successfully tagged acme/my-final-image:1.0
[root@master cow-test]# docker image ls
REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
acme/my-final-image   1.0                 0f8b98bb868d        24 seconds ago      63.2MB
acme/my-base-image    1.0                 72ee914ed695        55 seconds ago      63.2MB

檢視構建歷史:

[root@master cow-test]# docker history 72ee914ed695
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
72ee914ed695        4 minutes ago       /bin/sh -c #(nop) COPY dir:b5be11a9f1ec80f6d…   107B
56def654ec22        8 weeks ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>           8 weeks ago         /bin/sh -c mkdir -p /run/systemd && echo 'do…   7B
<missing>           8 weeks ago         /bin/sh -c [ -z "$(apt-get indextargets)" ]     0B
<missing>           8 weeks ago         /bin/sh -c set -xe   && echo '#!/bin/sh' > /…   745B
<missing>           8 weeks ago         /bin/sh -c #(nop) ADD file:4974bb5483c392fb5…   63.2MB
[root@master cow-test]# docker history 0f8b98bb868d
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
0f8b98bb868d        3 minutes ago       /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/app…   0B
72ee914ed695        4 minutes ago       /bin/sh -c #(nop) COPY dir:b5be11a9f1ec80f6d…   107B
56def654ec22        8 weeks ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>           8 weeks ago         /bin/sh -c mkdir -p /run/systemd && echo 'do…   7B
<missing>           8 weeks ago         /bin/sh -c [ -z "$(apt-get indextargets)" ]     0B
<missing>           8 weeks ago         /bin/sh -c set -xe   && echo '#!/bin/sh' > /…   745B
<missing>           8 weeks ago         /bin/sh -c #(nop) ADD file:4974bb5483c392fb5…   63.2MB

Notice that all the layers are identical except the top layer of the second image. All the other layers are shared between the two images, and are only stored once in /var/lib/docker/. The new layer actually doesn’t take any room at all, because it is not changing any files, but only running a command.

請注意,除了第二個映象的頂層之外,所有層都是相同的。所有其他層在兩個映象之間共享,並且僅在 /var/lib/docker/ 中儲存一次。實際上,新層根本沒有佔用任何空間,因為它不會更改任何檔案,而只是執行命令。

Note: The <missing> lines in the docker history output indicate that those layers were built on another system and are not available locally. This can be ignored.

注意:“ docker history”輸出中的“ ”行表示這些層是在另一個系統上構建的,並且在本地不可用。這可以忽略。

複製使容器高效

When you start a container, a thin writable container layer is added on top of the other layers. Any changes the container makes to the filesystem are stored here. Any files the container does not change do not get copied to this writable layer. This means that the writable layer is as small as possible.

啟動容器時,將在其他層之上新增一個薄的可寫容器層。容器對檔案系統所做的任何更改都儲存在此處。容器未更改的任何檔案都不會複製到此可寫層。這意味著可寫層儘可能小。

When an existing file in a container is modified, the storage driver performs a copy-on-write operation. The specifics steps involved depend on the specific storage driver. For the aufs, overlay, and overlay2 drivers, the copy-on-write operation follows this rough sequence:

當修改容器中的現有檔案時,儲存驅動將執行寫時複製操作。涉及的具體步驟取決於特定的儲存驅動。對於 aufsoverlayoverlay2 驅動程式,寫時複製操作遵循以下大致順序:

  • Search through the image layers for the file to update. The process starts at the newest layer and works down to the base layer one layer at a time. When results are found, they are added to a cache to speed future operations.

  • 在映象圖層中搜索要更新的檔案。該過程從最新層開始,一次向下一層到基礎層。找到結果後,會將它們新增到快取中以加快將來的操作。

  • Perform a copy_up operation on the first copy of the file that is found, to copy the file to the container’s writable layer.

  • 在找到的第一個檔案上執行 copy_up 操作,以將檔案複製到容器的可寫層。

  • Any modifications are made to this copy of the file, and the container cannot see the read-only copy of the file that exists in the lower layer.

  • 只要對該檔案的副本進行了任何修改,容器就看不到存在於較低層中的檔案的只讀副本。

Btrfs, ZFS, and other drivers handle the copy-on-write differently. You can read more about the methods of these drivers later in their detailed descriptions.

Btrfs,ZFS 和其他驅動程式以不同方式處理寫時複製。您可以在稍後的詳細說明中閱讀有關這些驅動程式方法的更多資訊。

Containers that write a lot of data consume more space than containers that do not. This is because most write operations consume new space in the container’s thin writable top layer.

寫入大量資料的容器比不寫入資料的容器消耗更多的空間。這是因為大多數寫操作會佔用容器的薄可寫頂層中的新空間。

Note: for write-heavy applications, you should not store the data in the container. Instead, use Docker volumes, which are independent of the running container and are designed to be efficient for I/O. In addition, volumes can be shared among containers and do not increase the size of your container’s writable layer.

注意:對於大量寫應用程式,您不應將資料儲存在容器中。取而代之的是使用 Docker 資料卷,它們獨立於正在執行的容器,並且旨在提高 I/O 效率。此外,卷可以在容器之間共享,而不會增加容器可寫層的大小。

A copy_up operation can incur a noticeable performance overhead. This overhead is different depending on which storage driver is in use. Large files, lots of layers, and deep directory trees can make the impact more noticeable. This is mitigated by the fact that each copy_up operation only occurs the first time a given file is modified.

copy_up 操作可能會導致明顯的效能開銷。該開銷因所使用的儲存驅動程式而異。大檔案,許多層和深層目錄樹可以使影響更加明顯。每個 copy_up 操作僅在第一次修改給定檔案時才發生,這可以緩解這種情況。

To verify the way that copy-on-write works, the following procedures spins up 5 containers based on the acme/my-final-image:1.0 image we built earlier and examines how much room they take up.

為了驗證寫時複製的工作方式,以下過程基於我們之前構建的 acme/my-final-image:1.0 映象啟動了5個容器,並檢查了它們佔用了多少空間。

[root@master ~]# 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
e588c4c170c87bf410352c3bbd604a1657cffd7cc6b7f6d288f4055a437b89fe
c1a4c1a2dbf6f5f3b0a408f34cf388805f1760ab069a1feb95ad029bf8e69adf
29db4486f4a4d6680f979db6d490427bf5bf3c9121df7157da1c162debc3ec45
7fbc5d8b34d5be94d3ff0877dff61261160f71ad92e81d7e2f96583496d68afd
fff65aa3ae7b6446da0dfea988aeceb108092e174a0efd024034ad096ba26c99
[root@master ~]# docker ps
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS                   NAMES
fff65aa3ae7b        acme/my-final-image:1.0   "bash"                   15 seconds ago      Up 14 seconds                               my_container_5
7fbc5d8b34d5        acme/my-final-image:1.0   "bash"                   15 seconds ago      Up 14 seconds                               my_container_4
29db4486f4a4        acme/my-final-image:1.0   "bash"                   16 seconds ago      Up 15 seconds                               my_container_3
c1a4c1a2dbf6        acme/my-final-image:1.0   "bash"                   16 seconds ago      Up 15 seconds                               my_container_2
e588c4c170c8        acme/my-final-image:1.0   "bash"                   16 seconds ago      Up 15 seconds                               my_container_1
5d1021ee8b24        nginx:alpine              "/docker-entrypoint.…"   2 weeks ago         Up 54 minutes       0.0.0.0:8080->80/tcp    goofy_mendel
497d0139b307        nginx:alpine              "/docker-entrypoint.…"   3 weeks ago         Up 58 minutes       0.0.0.0:32768->80/tcp   web
[root@master ~]# ls /var/lib/docker/containers
0a33d1388325e5dbcd0f051dbb25a82c6433b8d0c9844067e8a89021bc8c9d46  c1a4c1a2dbf6f5f3b0a408f34cf388805f1760ab069a1feb95ad029bf8e69adf
29db4486f4a4d6680f979db6d490427bf5bf3c9121df7157da1c162debc3ec45  e588c4c170c87bf410352c3bbd604a1657cffd7cc6b7f6d288f4055a437b89fe
497d0139b30750b8ce9c87df8802f48ead5dc5f1e18f29e8e52a18af8d8c8cf2  ed91cb09178c4d5bac13b93480dfa8006295dfceffa6e680cf19c5ea9f747115
5d1021ee8b2493f282512448bfebb33449422c6d7af0a231add658601658127c  fff65aa3ae7b6446da0dfea988aeceb108092e174a0efd024034ad096ba26c99
7fbc5d8b34d5be94d3ff0877dff61261160f71ad92e81d7e2f96583496d68afd
[root@master ~]# du -sh /var/lib/docker/containers/*
28K     /var/lib/docker/containers/0a33d1388325e5dbcd0f051dbb25a82c6433b8d0c9844067e8a89021bc8c9d46
24K     /var/lib/docker/containers/29db4486f4a4d6680f979db6d490427bf5bf3c9121df7157da1c162debc3ec45
28K     /var/lib/docker/containers/497d0139b30750b8ce9c87df8802f48ead5dc5f1e18f29e8e52a18af8d8c8cf2
28K     /var/lib/docker/containers/5d1021ee8b2493f282512448bfebb33449422c6d7af0a231add658601658127c
24K     /var/lib/docker/containers/7fbc5d8b34d5be94d3ff0877dff61261160f71ad92e81d7e2f96583496d68afd
24K     /var/lib/docker/containers/c1a4c1a2dbf6f5f3b0a408f34cf388805f1760ab069a1feb95ad029bf8e69adf
24K     /var/lib/docker/containers/e588c4c170c87bf410352c3bbd604a1657cffd7cc6b7f6d288f4055a437b89fe
28K     /var/lib/docker/containers/ed91cb09178c4d5bac13b93480dfa8006295dfceffa6e680cf19c5ea9f747115
24K     /var/lib/docker/containers/fff65aa3ae7b6446da0dfea988aeceb108092e174a0efd024034ad096ba26c99
[root@master ~]#

每個容器佔用 24k 的大小。

Not only does copy-on-write save space, but it also reduces start-up time. When you start a container (or multiple containers from the same image), Docker only needs to create the thin writable container layer.

寫時複製不僅可以節省空間,還可以縮短啟動時間。當啟動一個容器(或同一映象中的多個容器)時,Docker 只需要建立可寫的薄容器層。

If Docker had to make an entire copy of the underlying image stack each time it started a new container, container start times and disk space used would be significantly increased. This would be similar to the way that virtual machines work, with one or more virtual disks per virtual machine.

如果 Docker 每次啟動新容器都必須製作基礎映象堆疊的完整副本,則容器啟動時間和使用的磁碟空間將大大增加。這將類似於虛擬機器的工作方式,每個虛擬機器具有一個或多個虛擬磁碟。

總結

介紹了儲存驅動,Docker 映象,容器和層,所佔空間的大小,以及寫時複製技術。