【Docker】資料卷
參考教程:https://docs.docker.com/storage/volumes/
以下內容來自官方文件翻譯
環境
- virtual box 6.1
- centos 7.8
- 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 bebind
,volume
, ortmpfs
. This topic discusses volumes, so the type is alwaysvolume
. -
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 assource
orsrc
. -
The
destination
takes as its value the path where the file or directory is mounted in the container. May be specified asdestination
,dst
, ortarget
. -
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. -
裝載的型別,可以是
bind
,volume
或者tmpfs
。本主題討論資料卷,因此型別始終為volume
。 -
掛載的來源。對於命名卷,這是資料卷的名稱。對於匿名卷,省略此欄位。可以指定為
source
或者src
-
掛載的目的地是檔案或目錄掛載在容器中的路徑。可以指定為
destination
,dst
或者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
總結
介紹了資料卷的基礎使用,包括增加刪除等,使用資料卷儲存和共享資料,以及備份和恢復。