1. 程式人生 > 實用技巧 >【Docker】資料卷

【Docker】資料卷

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

環境

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

使用資料卷

Volumes are the preferred mechanism for persisting data generated by and used by Docker containers. While bind mounts are dependent on the directory structure and OS of the host machine, volumes are completely managed by Docker. Volumes have several advantages over bind mounts:

資料卷是持久化 Docker 容器生成和使用的資料的首選機制。因為繫結掛載依賴於主機的目錄結構和作業系統,資料卷完全由 Docker 管理。和繫結掛載相比,資料卷具有幾個優點:

  • Volumes are easier to back up or migrate than bind mounts.
  • You can manage volumes using Docker CLI commands or the Docker API.
  • Volumes work on both Linux and Windows containers.
  • Volumes can be more safely shared among multiple containers.
  • Volume drivers let you store volumes on remote hosts or cloud providers, to encrypt the contents of volumes, or to add other functionality.
  • New volumes can have their content pre-populated by a container.
  • Volumes on Docker Desktop have much higher performance than bind mounts from Mac and Windows hosts.
  • 資料卷比繫結掛載更容易備份或遷移。
  • 您可以使用 Docker CLI 命令或 Docker API 管理資料卷。
  • 資料卷在同時在 Linux 和 Windows 容器上工作。
  • 資料卷可以在多個容器之間更安全地共享。
  • 資料卷驅動程式允許您將卷儲存在遠端主機或雲提供商,以提供資料卷內容的加密或者其它功能。
  • 新資料卷的內容可以由容器預先填充。
  • 與來自 Mac 和 Windows 主機的繫結掛載相比,Docker Desktop 上的資料卷具有更高的效能。

In addition, volumes are often a better choice than persisting data in a container’s writable layer, because a volume does not increase the size of the containers using it, and the volume’s contents exist outside the lifecycle of a given container.

此外,資料卷通常比在容器的可寫層中儲存資料更好的選擇,因為卷不會增加使用它的容器的大小,並且卷的內容存在於給定容器的生命週期之外。

If your container generates non-persistent state data, consider using a tmpfs mount to avoid storing the data anywhere permanently, and to increase the container’s performance by avoiding writing into the container’s writable layer.

如果容器生成非永續性狀態資料,請考慮使用 tmpfs 掛載以避免將資料永久儲存在任何地方,並避免寫入容器的可寫層來提高容器的效能。

-v 和 -mount 的選擇

In general, --mount is more explicit and verbose. The biggest difference is that the -v syntax combines all the options together in one field, while the --mount syntax separates them. Here is a comparison of the syntax for each flag.

一般來說,--mount 更明確和冗長。最大的區別在於, -v 語法將所有選項合併到一個欄位中,而 --mount 語法將它們分開。下面是每個標誌的語法的比較。

If you need to specify volume driver options, you must use --mount.

如果需要指定資料卷驅動程式選項,則必須使用 --mount

  • -v or --volume: Consists of three fields, separated by colon characters (:). The fields must be in the correct order, and the meaning of each field is not immediately obvious.

    • In the case of named volumes, the first field is the name of the volume, and is unique on a given host machine. For anonymous volumes, the first field is omitted.
    • The second field is the path where the file or directory are mounted in the container.
    • The third field is optional, and is a comma-separated list of options, such as ro. These options are discussed below.
  • -v 或者 --volume:由三個欄位組成,用冒號(:)分隔。欄位必須按正確的順序排列,並且每個欄位的含義不是顯而易見。

    • 在命名卷的情況下,第一個欄位是卷的名稱,在給定的主機上是唯一的。對於匿名卷,省略第一個欄位。
    • 第二個欄位是將檔案或目錄掛載到容器中的路徑。
    • 第三個欄位是可選的,並且是逗號分隔的選項列表,例如 ro。下面將討論這些選項。
  • --mount: Consists of multiple key-value pairs, separated by commas and each consisting of a <key>=<value> tuple. The --mount syntax is more verbose than -v or --volume, but the order of the keys is not significant, and the value of the flag is easier to understand.

  • --mount:由多個鍵值對組成,用逗號分隔,每個鍵值對由 <key>=<value> 元組組成。--mount 語法比 -v--volume 更詳細,鍵的順序不重要,並且標誌的值更容易理解。

    • The type of the mount, which can be bind, volume, or tmpfs. This topic discusses volumes, so the type is always volume.

    • The source of the mount. For named volumes, this is the name of the volume. For anonymous volumes, this field is omitted. May be specified as source or src.

    • The destination takes as its value the path where the file or directory is mounted in the container. May be specified as destination, dst, or target.

    • The readonly option, if present, causes the bind mount to be mounted into the container as read-only.

    • The volume-opt option, which can be specified more than once, takes a key-value pair consisting of the option name and its value.

    • 裝載的型別,可以是 bindvolume 或者 tmpfs。本主題討論資料卷,因此型別始終為 volume

    • 掛載的來源。對於命名卷,這是資料卷的名稱。對於匿名卷,省略此欄位。可以指定為 source 或者 src

    • 掛載的目的地是檔案或目錄掛載在容器中的路徑。可以指定為 destinationdst 或者 target

    • 如果 readonly 存在,該選項只會掛載一個只讀的資料卷。

    • volume-opt 可以指定多次,採用鍵值對的形式。

資料卷的操作

資料卷的所有命令

[root@master ~]# docker volume

Usage:  docker volume COMMAND

Manage volumes

Commands:
  create      Create a volume
  inspect     Display detailed information on one or more volumes
  ls          List volumes
  prune       Remove all unused local volumes
  rm          Remove one or more volumes

Run 'docker volume COMMAND --help' for more information on a command.

列出資料卷

[root@master ~]# docker volume ls --help

Usage:  docker volume ls [OPTIONS]

List volumes

Aliases:
  ls, list

Options:
  -f, --filter filter   Provide filter values (e.g. 'dangling=true')
      --format string   Pretty-print volumes using a Go template
  -q, --quiet           Only display volume names

[root@master ~]# docker volume ls
DRIVER              VOLUME NAME
local               eab77839cbab7a3123c8151031dcd2fcc71aff7a8306613502a4866d0ff232a4
local               nexus-data

建立資料卷

[root@master ~]# docker volume create --help

Usage:  docker volume create [OPTIONS] [VOLUME]

Create a volume

Options:
  -d, --driver string   Specify volume driver name (default "local")
      --label list      Set metadata for a volume
  -o, --opt map         Set driver specific options (default map[])

[root@master ~]# docker volume create my-vol
my-vol

檢視資料卷

[root@master ~]# docker volume inspect --help

Usage:  docker volume inspect [OPTIONS] VOLUME [VOLUME...]

Display detailed information on one or more volumes

Options:
  -f, --format string   Format the output using the given Go template
[root@master ~]# docker volume inspect my-vol
[
    {
        "CreatedAt": "2020-10-31T06:38:43+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]
[root@master ~]#

刪除資料卷

[root@master ~]# docker volume rm --help

Usage:  docker volume rm [OPTIONS] VOLUME [VOLUME...]

Remove one or more volumes. You cannot remove a volume that is in use by a container.

Aliases:
  rm, remove

Examples:

$ docker volume rm hello
hello


Options:
  -f, --force   Force the removal of one or more volumes

[root@master ~]# docker volume remove my-vol
my-vol

使用未命名資料卷

[root@master ~]# docker run -p8080:80 --mount dst=/usr/share/nginx/html -d nginx
91f5469eeeb4ffe12c385edcab40fba3b0865d366aa33b5f49010ab6cfc84cab
[root@master ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
91f5469eeeb4        nginx               "/docker-entrypoint.…"   9 seconds ago       Up 7 seconds        0.0.0.0:8080->80/tcp   wonderful_booth
[root@master ~]# docker volume ls
DRIVER              VOLUME NAME
local               0d34810d835e236577f6f101f0b1ebf0174973ae4a38b9d938ecf6f269a49362
local               eab77839cbab7a3123c8151031dcd2fcc71aff7a8306613502a4866d0ff232a4
local               nexus-data

[root@master ~]# docker container inspect 91 --format '{{json .Mounts}}' | jq
[
  {
    "Type": "volume",
    "Name": "0d34810d835e236577f6f101f0b1ebf0174973ae4a38b9d938ecf6f269a49362",
    "Source": "/var/lib/docker/volumes/0d34810d835e236577f6f101f0b1ebf0174973ae4a38b9d938ecf6f269a49362/_data",
    "Destination": "/usr/share/nginx/html",
    "Driver": "local",
    "Mode": "z",
    "RW": true,
    "Propagation": ""
  }
]

使用命名資料卷

[root@master ~]# docker run -P --mount src=nginx-volume,dst=/usr/share/nginx/html -d nginx
b3d9ca1cf5c1853961e004d451a289f4641d8a4af15796f85034298d3ac11ead
[root@master ~]# docker port b3d
80/tcp -> 0.0.0.0:32768
[root@master ~]#
[root@master ~]# docker volume ls
DRIVER              VOLUME NAME
local               0d34810d835e236577f6f101f0b1ebf0174973ae4a38b9d938ecf6f269a49362
local               eab77839cbab7a3123c8151031dcd2fcc71aff7a8306613502a4866d0ff232a4
local               nexus-data
local               nginx-volume
[root@master ~]# docker container inspect b3d --format '{{json .Mounts}}' | jq
[
  {
    "Type": "volume",
    "Name": "nginx-volume",
    "Source": "/var/lib/docker/volumes/nginx-volume/_data",
    "Destination": "/usr/share/nginx/html",
    "Driver": "local",
    "Mode": "z",
    "RW": true,
    "Propagation": ""
  }
]

檢視資料卷詳情

[root@master ~]# docker volume inspect nginx-volume
[
    {
        "CreatedAt": "2020-10-31T07:12:26+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/nginx-volume/_data",
        "Name": "nginx-volume",
        "Options": null,
        "Scope": "local"
    }
]

只讀資料卷


[root@master ~]# docker run -P --mount src=nginx-volume,dst=/usr/share/nginx/html,readonly -d nginx
7b5d9210f71f1ed7dc733b7f3151351ea41cb54b86d04f8b173fbd5f4406db7f
[root@master ~]# docker container inspect 7b5 --format '{{json .Mounts}}' | jq
[
  {
    "Type": "volume",
    "Name": "nginx-volume",
    "Source": "/var/lib/docker/volumes/nginx-volume/_data",
    "Destination": "/usr/share/nginx/html",
    "Driver": "local",
    "Mode": "z",
    "RW": false,
    "Propagation": ""
  }
]

資料卷共享資料

[root@master ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                   NAMES
7b5d9210f71f        nginx               "/docker-entrypoint.…"   4 minutes ago       Up 4 minutes        0.0.0.0:32769->80/tcp   pedantic_hugle
b3d9ca1cf5c1        nginx               "/docker-entrypoint.…"   9 minutes ago       Up 9 minutes        0.0.0.0:32768->80/tcp   boring_benz
[root@master ~]# docker exec -it b3d bash
root@b3d9ca1cf5c1:/# cd usr/share/nginx/html/
root@b3d9ca1cf5c1:/usr/share/nginx/html# ls
50x.html  index.html
root@b3d9ca1cf5c1:/usr/share/nginx/html# echo 'hello world' > index.html
root@b3d9ca1cf5c1:/usr/share/nginx/html# exit
exit
[root@master ~]# curl localhost:32769
hello world
[root@master ~]# docker volume inspect nginx-volume
[
    {
        "CreatedAt": "2020-10-31T07:12:26+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/nginx-volume/_data",
        "Name": "nginx-volume",
        "Options": null,
        "Scope": "local"
    }
]
[root@master ~]# cat /var/lib/docker/volumes/nginx-volume/_data/index.html
hello world

資料卷的備份和恢復

生成資料卷

[root@master ~]# docker run -P -d --mount type=volume,src=nginx-volume,dst=/usr/share/nginx/html nginx:alpine
6264f7e1c20b4799845ef809fb7e065febccb25e0b75d7cfc2c32b78b76a8980
[root@master ~]# docker ps
CONTAINER ID  IMAGE                           COMMAND               CREATED         STATUS            PORTS                  NAMES
6264f7e1c20b  docker.io/library/nginx:alpine  nginx -g daemon o...  22 seconds ago  Up 5 seconds ago  0.0.0.0:44425->80/tcp  objective_johnson

修改掛載內容

[root@master ~]# docker exec -it 626 /bin/sh
/ # ls
bin                   etc                   mnt                   run                   tmp
dev                   home                  opt                   sbin                  usr
docker-entrypoint.d   lib                   proc                  srv                   var
docker-entrypoint.sh  media                 root                  sys
/ # ll
/bin/sh: ll: not found
/ # cd usr/share/nginx/html/
/usr/share/nginx/html # ll
/bin/sh: ll: not found
/usr/share/nginx/html # ls
50x.html    index.html
/usr/share/nginx/html # echo "hello world!" > index.html
/usr/share/nginx/html # exit
[root@master ~]# curl localhost:44425
hello world!

檢視資料卷位置

[root@master ~]# docker volume ls
dockeDRIVER   VOLUME NAME
local    nginx-volume
[root@master ~]# docker volume inspect nginx-volume
[
     {
          "Name": "nginx-volume",
          "Driver": "local",
          "Mountpoint": "/var/lib/containers/storage/volumes/nginx-volume/_data",
          "CreatedAt": "2020-11-02T12:11:26.383688716+08:00",
          "Labels": {

          },
          "Scope": "local",
          "Options": {

          }
     }
]
[root@master ~]# cd /var/lib/containers/storage/volumes/

備份資料卷

[root@master volumes]# tar -zcvf nginx-volume.tar.gz nginx-volume
nginx-volume/
nginx-volume/_data/
nginx-volume/_data/50x.html
nginx-volume/_data/index.html
[root@master volumes]# mv nginx-volume.tar.gz ~

刪除資料卷

[root@master volumes]# docker ps
CONTAINER ID  IMAGE                           COMMAND               CREATED        STATUS            PORTS                  NAMES
6264f7e1c20b  docker.io/library/nginx:alpine  nginx -g daemon o...  3 minutes ago  Up 3 minutes ago  0.0.0.0:44425->80/tcp  objective_johnson
[root@master volumes]# docker stop 626
6264f7e1c20b4799845ef809fb7e065febccb25e0b75d7cfc2c32b78b76a8980
[root@master volumes]# docker container prune
6264f7e1c20b4799845ef809fb7e065febccb25e0b75d7cfc2c32b78b76a8980
[root@master volumes]# docker volume ls
DRIVER   VOLUME NAME
local    nginx-volume
[root@master volumes]# docker volume rm nginx-volume
nginx-volume

啟動新容器

[root@master volumes]# docker run -P -d --name web --mount type=volume,src=nginx-volume,dst=/usr/share/nginx/html nginx:alpine

8f5b867e5f937c84729f09031a1d44e1d1e36599ee25262775113a2e9da3c4b5
[root@master volumes]# ls
nginx-volume
[root@master volumes]# tar -zxvf ~/nginx-volume.tar.gz
nginx-volume/
nginx-volume/_data/
nginx-volume/_data/50x.html
nginx-volume/_data/index.html
[root@master volumes]# ll
total 0
drwx------. 3 root root 19 Nov  2 12:11 nginx-volume

驗證還原效果

[root@master volumes]# docker ps
CONTAINER ID  IMAGE                           COMMAND               CREATED             STATUS                 PORTS                  NAMES
8f5b867e5f93  docker.io/library/nginx:alpine  nginx -g daemon o...  About a minute ago  Up About a minute ago  0.0.0.0:36962->80/tcp  web
[root@master volumes]# curl localhost:36962
hello world!

檢視資料卷掛載變化

資料卷的實現方式是使用 Linux 的掛載實現的。同時,在使用 commit 建立映象時,資料卷的內容也不會被提交。

[root@master _data]# docker container diff ed
C /var
C /var/cache
C /var/cache/nginx
A /var/cache/nginx/client_temp
A /var/cache/nginx/fastcgi_temp
A /var/cache/nginx/proxy_temp
A /var/cache/nginx/scgi_temp
A /var/cache/nginx/uwsgi_temp
C /run
A /run/nginx.pid
C /etc
C /etc/nginx
C /etc/nginx/conf.d
C /etc/nginx/conf.d/default.conf

總結

介紹了資料卷的基礎使用,包括增加刪除等,使用資料卷儲存和共享資料,以及備份和恢復。