我想在docker中挂载一个主机目录,在外面实际上是只读/只.但我希望它以读/写的形式出现在容器内.
这样我可以写入文件/目录,但不能在外部进行更改.这可能是使用某种覆盖过程吗?
Wox*_*xxy 17
编辑:查看@ javabrett的评论:
尽管这个解决方案有一个日落,但观察到有关在4.8内核和更新版本上禁用overlay-upperdir-on-overlay的问题. - javabrett 7月23日5:55
请参阅:https://stackoverflow.com/a/50917037/644504
这就是我做的:
在主持人:
将目录加载为只读.
/path/on/client
在客户端:
在客户端上使用OverlayFS覆盖从主机挂载的只读目录.
overlayfs
然后overlayfs用来读/写文件.
编辑:如果您的主机上有3.18+内核,您可能更喜欢在客户端上使用它:
rm
哪个不是overlay.随着/path/on/client我就暂时无法使用的问题overlayfs.overlayfs为我解决了这个问题.
BMi*_*tch 16
您无需运行特权容器,也无需任何其他 3rd 方工具,即可使用本地卷驱动程序执行此操作。本地卷驱动程序会将任何选项传递给挂载系统调用,因此您可以使用挂载执行的任何操作都可以作为 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.
Run Code Online (Sandbox Code Playgroud)
接下来,让我们使用覆盖选项创建一个命名卷并使用它运行一个容器:
$ 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
Run Code Online (Sandbox Code Playgroud)
然后,让我们用一个--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
Run Code Online (Sandbox Code Playgroud)
最后,让我们创建一个 compose 文件:
$ 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
Run Code Online (Sandbox Code Playgroud)
一切都在运行,让我们验证数据文件是否存在:
$ 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
Run Code Online (Sandbox Code Playgroud)
接下来,我们可以对容器 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
Run Code Online (Sandbox Code Playgroud)
验证每个容器看到的变化,或缺乏变化:
$ 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.
Run Code Online (Sandbox Code Playgroud)
并显示主机目录不变:
$ 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.
Run Code Online (Sandbox Code Playgroud)
更改都只对上层目录进行:
$ 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
Run Code Online (Sandbox Code Playgroud)
删除容器和卷后,您需要手动删除上层目录。正如 docker 不会为您创建它们一样,它也不会删除它们,就像您自己运行 mount 命令一样。
drz*_*raf 10
不再是容器内部的选项(可能是因为在 ~ 4.4 kernels 中禁用了overlay-over-overlay )
$ uname -a && \
docker run --privileged --rm debian:latest sh -c "mkdir upper lower work merged && mount -t overlay overlay -olowerdir=lower,upperdir=upper,workdir=work merged/; dmesg|tail -1"
Linux preprod 4.9.0-6-amd64 #1 SMP Debian 4.9.88-1+deb9u1 (2018-05-07) x86_64 GNU/Linux
mount: wrong fs type, bad option, bad superblock on overlay,
missing codepage or helper program, or other error
In some cases useful info is found in syslog - try
dmesg | tail or so.
[288426.860631] overlayfs: filesystem on 'upper' not supported as upperdir
Run Code Online (Sandbox Code Playgroud)
无论如何, 另一种方法是在主机上创建覆盖并将其绑定到来宾:
$ mkdir upper lower work merged && \
touch upper/up lower/low && \
sudo mount -t overlay overlay -olowerdir=lower,upperdir=upper,workdir=work merged/ && \
docker run --rm -v $(pwd)/merged:/tmp/merged debian:latest sh -c "touch /tmp/merged/new-from-container"
Run Code Online (Sandbox Code Playgroud)
$ ls upper/ lower/ merged/
lower/:
low
merged/:
low new-from-container up
upper/:
new-from-container up
Run Code Online (Sandbox Code Playgroud)
如果您避免将 upperdir 设置为本地目录(即已经是覆盖层),则这是可能的。但你可以使用 tmpfs 代替(在内核 4.9 上测试):
# On the host to run the container
docker run --cap-add=SYS_ADMIN -i -t -v ~/host-folder-to-mount:/root/folder-ro:ro ubuntu
# Inside the container
# Need to create the upper and work dirs inside a tmpfs.
mkdir -p /tmp/overlay && \
mount -t tmpfs tmpfs /tmp/overlay && \
mkdir -p /tmp/overlay/{upper,work} && \
mkdir -p /root/folder && \
mount -t overlay overlay -o lowerdir=/root/folder-ro,upperdir=/tmp/overlay/upper,workdir=/tmp/overlay/work /root/folder
Run Code Online (Sandbox Code Playgroud)
所有学分均转到https://gist.github.com/detunized/7c8fc4c37b49c5475e68ef9574587eee
| 归档时间: |
|
| 查看次数: |
7198 次 |
| 最近记录: |