前天电脑出现了bug, Docker Desktop 里所有的 containerimage 都消失了。万幸今天它们又都出现了,还是提醒了我将 container 映射到本地的重要性。学习了docker volume的使用方法,特此记录。

1. 创建和管理volume

这里我的volume 命名为 zoe-volume,并在 window11WSL2-Ubuntu22.04上操作。

# 创建volume
docker volume create zoe-volume
# 查看volume list
docker volume ls
DRIVER    VOLUME NAME
local     zoe-volume
# 检查volume
docker volume inspect zoe-volume
[
    {
        "CreatedAt": "2024-04-23T07:22:56Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/zoe-volume/_data",
        "Name": "zoe-volume",
        "Options": null,
        "Scope": "local"
    }
]
# 移除volume
docker volume rm zoe-volume
# 清理无用的 volume(不包含任何container的那种)
docker volume prune

默认创建的volume是没有compose.yaml,可以自行创建。

2. 创建一个container挂载至本地volume

这个是最简单、方便的,在创建 container 初期就确定挂载 volume
注意,其中target参数是(相对于容器根目录)容器内挂载点的路径,而不是针对宿主机的绝对路径。

docker run --mount source=<volume_name>,target=<mount_path> <image_name>

示例如下:

(base) zoe@MSI:~$ docker run -it --name kinetic_t1 --mount source=zoe-volume,target=/home/zoe/volume ubuntu-16.04:kinetic bash
root@84bb2071e59f:/#

多个 container 可以连接到同一个 volume 中。如下图所示。

Windows11下Docker使用记录(三)-LMLPHP
Windows11下Docker使用记录(三)-LMLPHP

# 添加readonly参数,只读 volume
(base) zoe@MSI:~$ docker run -it --name kinetic_t5 --mount source=zoe-volume,target=/app,readonly ubuntu-16.04:kinetic bash
root@84bb2071e59f:/#

3. docker -v和–mount的区别

docker run -it --name kinetic_t2 -v zoe-volume:/data ubuntu-16.04:kinetic bash
docker run -it --name kinetic_t4 --volume zoe-volume:/app ubuntu-16.04:kinetic bash 

-v--mount功能几乎一致,--mount 参数指代(key=value结构)要更明确些,-v:分割参数;此外,service 功能只可用--mount

4. volume driver

volume driver 用于管理 volume的拓展机制,允许用户使用不同的存储后端来管理卷。例如,

  1. 支持不同的储存后端:云储存。
  2. 提供更多功能性和性能优化:加密SSH。
  3. 集成第三方存储服务:NFS(Network File System)。
  4. 提高可拓展性和弹性。

5. container间共享内容

几个container挂载在同一个volume中是可以共享文件的。
当前有三个containerkinetic_t2kinetic_t4kinetic_t1,挂载在同一个volumezoe-volume

(base) zoe@MSI:~$ docker container ls
CONTAINER ID   IMAGE                  COMMAND   CREATED        STATUS        PORTS     NAMES
c1d3a23fcb36   ubuntu-16.04:kinetic   "bash"    10 hours ago   Up 10 hours   22/tcp    kinetic_t2
a86b996add5c   ubuntu-16.04:kinetic   "bash"    11 hours ago   Up 11 hours   22/tcp    kinetic_t4
84bb2071e59f   ubuntu-16.04:kinetic   "bash"    18 hours ago   Up 18 hours   22/tcp    kinetic_t1

kinetic_t2挂载点创建多个文件:

cd /data
touch test.txt
touch a{1..10}.txt
# 在 kinetic_t2 挂载点可见
root@c1d3a23fcb36:/data# ls
a1.txt  a10.txt  a2.txt  a3.txt  a4.txt  a5.txt  a6.txt  a7.txt  a8.txt  a9.txt  test.txt

可以在其他两个container中找到

# 在 kinetic_t1 挂载点可见
root@84bb2071e59f:/home/zoe/volume# ls
a1.txt  a10.txt  a2.txt  a3.txt  a4.txt  a5.txt  a6.txt  a7.txt  a8.txt  a9.txt  test.txt
# 在 kinetic_t4 挂载点可见
root@a86b996add5c:/app# ls
a1.txt  a10.txt  a2.txt  a3.txt  a4.txt  a5.txt  a6.txt  a7.txt  a8.txt  a9.txt  test.txt

Docker Desktop上也可以看到
Windows11下Docker使用记录(三)-LMLPHP

6. 从volume 中恢复container 数据

这是我最看重的功能。但之前我有误解,我认为备份是备份一个完整的container,但其实是备份指定文件夹内的数据
恢复的本质是用image新建一个container并把原来container备份的数据复制过去。
所以,我认为完整备份一个container的办法依然是及时将其commitimage

以下就是我新建一个containerkinetic_t6,并在其中恢复 kinetic_t2 中的数据

# 创建一个可交互的 kinetic_t6 容器
docker run -it --name kinetic_t6 --volumes-from kinetic_t2 -v $(pwd):/backup ubuntu-16.04:kinetic bash
 
# 在打开的容器中 把 kinetic_t2的/data中的内容 打包至 kinetic_t6de /backup/backup.tar中
tar cvf /backup/backup.tar /data

# 解压
tar xvf /backup/backup.tar

解压后会得到kinetic_t2/data文件夹和对应的数据,如下所述。

root@017b80fe129d:/backup/data# ls
a1.txt  a10.txt  a2.txt  a3.txt  a4.txt  a5.txt  a6.txt  a7.txt  a8.txt  a9.txt  test.txt
04-25 07:28