Docker 数据卷使用

数据卷特点

在容器中,文件环境是由 UFS(Union File System)提供的临时层。所有在容器中进行的操作都会随着容器的删除而被丢弃。为了实现从外部获取文件并进行持久化存储的目标,Docker 提出了数据卷(Data Volume)的概念。数据卷是一个挂载在容器内文件系统中的文件或目录,每次启动容器时都会自动挂载到容器中,并且它可以脱离容器的生命周期而独立存在。

数据卷作为容器中的一个特殊文件或目录,与其他文件或目录有很大的区别:

  • 数据卷中的数据不继承自镜像,也不受容器临时层管理的范围。因此,数据卷没有写时复制机制,文件操作的效果会立即生效。这些数据也不会被 docker commit 命令提交到新的镜像中。
  • 数据卷不依赖于容器,它独立于容器之外。多个容器可以共享同一个数据卷,通过数据卷可以实现容器之间的文件共享和数据交互。

数据卷提供了一种方便的方式来处理容器内文件的持久化和共享需求。通过使用数据卷,我们可以更灵活地管理容器中的数据,并实现容器之间的文件共享。

创建数据卷

在创建容器时,可以同时创建数据卷。通过 -v 参数向容器中挂载一个数据卷,Docker 会自动创建该数据卷:

[root@server4 ~]$ docker create --name vdisk -v /disk alpine
000385b2005b5f79c1d1d05df5c981ac4dd3cffe1cc4d272691660151aebd26c

以上命令为名为 vdisk 的容器创建了一个路径为 /disk 的数据卷。如果需要,可以多次使用 -v 参数来挂载多个数据卷。

此外,可以使用 docker volume create 命令创建一个自定义名称为 disk1 的数据卷:

[root@server4 ~]$ docker volume create --name disk1
disk1

所有创建的数据卷默认存放在 /var/lib/docker/volumes/ 路径下。

查询数据卷

可以使用 docker volume ls 命令查看已创建的数据卷列表:

[root@server4 ~]$ docker volume ls
DRIVER    VOLUME NAME
local     21470509cc37589319a7eab45bdb9ca12ad4d500ff49228ce0b65cd985fb62fb
local     disk1

可以使用 docker volume inspect 命令查看指定数据卷的基本信息:

[root@server4 ~]$ docker volume inspect disk1
[
    {
        "CreatedAt": "2021-10-22T09:58:06+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/disk1/_data",
        "Name": "disk1",
        "Options": {},
        "Scope": "local"
    }
]

挂载数据卷

在创建容器时,已创建的数据卷会自动挂载到容器中。而使用 docker createdocker run 命令创建容器时,可以使用 -v 选项指定挂载数据卷,格式为:-v <volume_name>:<container_path>。数据卷可以绕过分层的联合文件系统,为 Docker 提供持久数据或共享数据。这也意味着对数据卷的修改会直接生效,但当提交或创建镜像时,数据卷不会被包含在镜像中。

在将宿主机目录或文件挂载到容器时,默认权限是读写(rw),可以对数据的权限进行限制。例如,以只读(ro)的方式挂载目录 /root/disk1,可以保证容器内的程序无法修改该目录中的数据:

[root@server4 ~]$ docker create --name vdisk2 -v /root/disk1:/disk1:ro alpine
d44ab826d5ddd43bcdfa966648acb57d19f1982f22b28053f6e4b3b223118351

有时候,希望将数据保存在内存中而非宿主机或容器中,可以使用 --tmpfs 参数来挂载只存在于内存中的 tmpfs 数据卷。

删除数据卷

可以使用 docker volume rm 命令来删除数据卷:

[root@server4 ~]$ docker volume rm disk1
disk1
[root@server4 ~]$ ll /var/lib/docker/volumes/disk1/
ls: cannot access /var/lib/docker/volumes/disk1/: No such file or directory

删除数据卷时,对应的本地目录也会被一并删除。

如果是与容器一同创建的数据卷,最好使用 -v 参数一起删除:

[root@server4 ~]$ docker rm -v 000385b 

批量删除数据卷可以先使用 docker volume ls -q 命令查询数据卷的 ID,然后再进行删除:

[root@server4 ubutu-trusty]$ docker volume rm $(docker volume ls -q)

数据卷容器

数据卷容器是专门用于存放数据卷的容器,它并不直接管理或控制数据卷,只是作为其他容器使用数据卷的桥梁。其作用是为了保证数据卷的安全性,防止随着其他容器的删除而被删除。

创建数据卷容器的方法与普通容器的创建方法没有区别,数据卷容器不需要保持运行。创建数据卷容器时所使用的数据卷目录,将作为其他容器连接到该数据卷容器时访问数据卷的目录。

例如,创建一个专门用于存放日志的数据卷容器:

[root@server4 ~]$ docker create --name logdata -v /logs alpine 
118002bf522df93e5e31011c74f0760d317ae235f23dca24f413068a1abe2d7a

在需要使用数据卷的容器中,可以使用 --volumes-from 参数挂载指定数据卷容器中的所有数据卷:

[root@server4 ~]$ docker run -it --rm --volumes-from logdata ubuntu:18.04 /bin/bash
root@7baf237b2484:/# ll -d /logs
drwxr-xr-x. 2 root root 6 Oct 22 02:49 /logs/

也可以多次使用 --volumes-from 参数来挂载多个不同的数据卷容器,以同时使用多个数据卷。

数据卷备份

使用数据卷容器可以方便地备份数据卷的内容。通过创建一个新的容器,将数据卷容器和宿主机目录连接起来,然后执行打包命令即可快速备份数据卷:

[root@server4 ~]$ docker run -it --volumes-from logdata -v $(pwd):/backup --rm ubuntu:18.04 tar cf /backup/logdata.tar /logs
tar: Removing leading `/' from member names
[root@server4 ~]$ ll logdata.tar 
-rw-r--r--. 1 root root 10240 Oct 22 11:10 logdata.tar

要恢复数据,则需要反向操作:

[root@server4 ~]$ docker run -it --volumes-from logdata -v $(pwd):/backup --rm ubuntu:18.04 tar xf /backup/logdata.tar