您可以使用本地卷驱动程序在不运行特权容器和任何其他第三方工具的情况下执行此操作。本地卷驱动程序会将任何选项传递给 mount 系统调用,因此您可以使用 mount 做的任何事情都可以作为 docker 中的卷来执行。唯一的前提是您提前创建覆盖目录并自己清理它们。
首先,让我们创建目录和一些只读数据:
$ mkdir -p {ro-data,upper1,upper2,upper3,work1,work2,work3}
$ ls
ro-data upper1 upper2 upper3 work1 work2 work3
$ vi ro-data/data.txt
$ cat ro-data/data.txt
This is a data file.
It should be read-only on the host upper dir.
接下来,让我们使用覆盖选项创建一个命名卷并使用它运行一个容器:
$ docker volume create --driver local --opt type=overlay \
--opt o=lowerdir=${PWD}/ro-data,upperdir=${PWD}/upper1,workdir=${PWD}/work1 \
--opt device=overlay overlay1
overlay1
$ docker container run -d --rm -v overlay1:/data --name cont1 busybox tail -f /dev/null
a6269cb6c68469aa4f57aae554c5f0823f1103715334b3719c5567abc7d55daa
然后,让我们对运行--mount 选项执行相同的操作,由于嵌套的逗号分隔字符串,它会稍微复杂一些。转义引号可以解决这个问题:
$ docker run -d --rm \
--mount type=volume,dst=/data,volume-driver=local,volume-opt=type=overlay,\"volume-opt=o=lowerdir=${PWD}/ro-data,upperdir=${PWD}/upper2,workdir=${PWD}/work2\",volume-opt=device=overlay \
--name cont2 busybox tail -f /dev/null
7329ae4ba4046782166b045611ecccb129f5e557df7eb4da95ec9063a0fe234e
最后,让我们编写一个文件:
$ vi docker-compose.yml
$ cat docker-compose.yml
version: '3'
volumes:
overlay3:
driver: local
driver_opts:
type: overlay
o: lowerdir=${PWD}/ro-data,upperdir=${PWD}/upper3,workdir=${PWD}/work3
device: overlay
services:
overlay3:
image: busybox
command: tail -f /dev/null
container_name: cont3
volumes:
- overlay3:/data
$ docker-compose up -d
Creating network "vol-overlay_default" with the default driver
Creating volume "vol-overlay_overlay3" with local driver
Creating cont3 ... done
一切都在运行,让我们验证数据文件是否存在:
$ docker exec cont1 ls -l /data
total 4
-rw-r--r-- 1 1000 1000 67 Nov 8 16:29 data.txt
$ docker exec cont2 ls -l /data
total 4
-rw-r--r-- 1 1000 1000 67 Nov 8 16:29 data.txt
$ docker exec cont3 ls -l /data
total 4
-rw-r--r-- 1 1000 1000 67 Nov 8 16:29 data.txt
接下来,我们可以对容器1中的目录进行一些修改,并删除容器2中的文件:
$ echo "container 1 adds lines" | docker exec -i cont1 tee -a /data/data.txt
container 1 adds lines
$ echo "writing to another file" | docker exec -i cont1 tee -a /data/container1.txt
writing to another file
[11:48:30] [bmitch@bmitch-asusr556l:~/data/docker/test/vol-overlay] [master]
$ docker exec cont2 rm /data/data.txt
验证每个容器是否有变化:
$ docker exec cont1 ls -l /data
total 8
-rw-r--r-- 1 root root 24 Nov 8 16:48 container1.txt
-rw-r--r-- 1 1000 1000 90 Nov 8 16:47 data.txt
$ docker exec cont2 ls -l /data
total 0
$ docker exec cont3 ls -l /data
total 4
-rw-r--r-- 1 1000 1000 67 Nov 8 16:29 data.txt
$ docker exec cont1 cat /data/data.txt
This is a data file.
It should be read-only on the host upper dir.
container 1 adds lines
$ docker exec cont3 cat /data/data.txt
This is a data file.
It should be read-only on the host upper dir.
并显示主机目录不变:
$ ls -l ro-data
total 4
-rw-r--r-- 1 bmitch bmitch 67 Nov 8 11:29 data.txt
$ cat ro-data/data.txt
This is a data file.
It should be read-only on the host upper dir.
所有更改都只针对上层目录:
$ ls -l upper*
upper1:
total 8
-rw-r--r-- 1 root root 24 Nov 8 11:48 container1.txt
-rw-r--r-- 1 bmitch bmitch 90 Nov 8 11:47 data.txt
upper2:
total 0
c--------- 1 root root 0, 0 Nov 8 11:48 data.txt
upper3:
total 0
删除容器和卷后,您需要手动删除上层目录。就像 docker 不会为你创建它们一样,它也不会删除它们,就像你自己运行 mount 命令一样。