以下Dockerfile在构建时会引发错误。有没有办法在构建容器时能够mount
与overlay
一起使用?
Dockerfile
FROM ubuntu:15.10
RUN mkdir /var/data \
&& mkdir /var/data/delta \
&& mkdir /var/data/delta/changes \
&& mkdir /var/data/delta/workdir \
&& mkdir /var/data/merged \
&& mkdir /var/data/lower
RUN mount -t overlay overlay -o lowerdir=/var/data/lower,upperdir=/var/data/delta/changes,workdir=/var/data/delta/workdir /var/data/merged
错误
...
Step 2 : RUN mount -t overlay overlay -o lowerdir=/var/data/lower,upperdir=/var/data/delta/changes,workdir=/var/data/delta/workdir /var/data/merged
---> Running in 37434cc88e15
mount: overlay is write-protected, mounting read-only
mount: cannot mount overlay read-only
Removing intermediate container 37434cc88e15
The command '/bin/sh -c mount -t overlay overlay -o lowerdir=/var/data/lower,upperdir=/var/data/delta/changes,workdir=/var/data/delta/workdir /var/data/merged' returned a non-zero code: 32
注意
我尝试在ubuntu:15.10
容器中运行下面的mount命令,它会给出相同的错误。如果容器以--privileged
启动,则命令有效。
答案 0 :(得分:2)
在构建容器时,有没有办法可以
mount
与overlay
一起使用?
简短回答:No, and there won't be any time soon。
似乎共识是,构建期间的任何类型的特权操作都会破坏映像可移植性契约,因为它可能会修改主机系统。如果不同的系统然后拉动并运行这样的图像而不是从源构建它,则从结果容器的角度来看,主机将处于无效状态。
请记住, docker build 通过使用(松散)这些操作完成Dockerfile
中的每个步骤/图层来工作:
因此,在这种情况下,特权构建操作显然可以突破临时容器并触摸主机。没有bueno。
那么,做什么?
更新 - 2015-10-24:失败。请参阅下面的解决方案2以了解正常工作。
注意:YMMV取决于Docker版本,存储/图形驱动程序等。这里是我的 docker info ,用于比较:
Containers: 12
Images: 283
Storage Driver: overlay
Backing Filesystem: extfs
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 4.1.10-040110-generic
Operating System: Ubuntu 15.04
CPUs: 4
Total Memory: 7.598 GiB
Name: agthinkpad
ID: F6WH:LNV4:HH66:AHYY:OGNI:OTKN:UALY:RD52:R5L5:ZTGA:FYBT:SWA4
WARNING: No swap limit support
嗯,我很惊讶地发现很难通过 docker commit 将装载物烘焙成图像。 /proc
文件系统,其中内核(更具体地来说,/proc/self/mounts
从容器内部写入安装元数据的文件表示),看起来根本不会被Docker持久化。据我所知,无论如何 - /var/lib/docker/overlay/<container-root-lower>/root/proc
为空,/var/lib/docker/overlay/<container-root-upper>/upper/proc
不存在。
我认为/proc
可以通过卷进行操作,并且确实找到了一些2年以上的引用来绑定挂载/proc:/proc
以实现可能没有人应该尝试的事情(像这样,可能?),但似乎这根本不再起作用了。尝试将mount /proc
绑定到主机目录或甚至只是创建一个卷现在是一个致命的错误,即使 docker run --privileged :
Code: System error
Message: "/var/lib/docker/overlay/c091a331f26bed12f22f19d73b139ab0c5b9971ea24aabbfad9c6482805984c9/merged/proc"
cannot be mounted because it is located inside "/proc"
Frames:
---
0: setupRootfs
Package: github.com/opencontainers/runc/libcontainer
File: rootfs_linux.go@37
---
1: Init
Package: github.com/opencontainers/runc/libcontainer.(*linuxStandardInit)
File: standard_init_linux.go@52
---
2: StartInitialization
Package: Error response from daemon: Cannot start container c091a331f26bed12f22f19d73b139ab0c5b9971ea24aabbfad9c6482805984c9: [8] System error: "/var/lib/docker/overlay/c091a331f26bed12f22f19d73b139ab0c5b9971ea24aabbfad9c6482805984c9/merged/proc" cannot be mounted because it is located inside "/proc"
对于一个不需要在通过启动/入口点脚本从图像生成的容器中运行 mount ... 的方法,我真的不知道从哪里去这点。因为/proc/self/mounts
由内核管理,更不用说不可写,这可能永远不可能。希望我能忽视某些事情,有人可以指出我正确的方向。
host$
uname -a
Linux agthinkpad 4.1 .10-040110-generic#201510030837 SMP Sat Oct 3 12:38:41 UTC 2015 x86_64 x86_64 x86_64 GNU / Linux
host$
mkdir / tmp / overlay-test&amp;&amp; cd / tmp / overlay-test
<强> ./Dockerfile
强>:
FROM debian:jessie
RUN apt-get update && apt-get install -y curl jq
WORKDIR /usr/local/sbin
# Locate and fetch the latest version of gosu
RUN ["/bin/bash", "-c", "curl -o ./gosu -sSL \"$( \
curl -s https://api.github.com/repos/tianon/gosu/releases/latest \
| jq --raw-output \
'.assets[] | select(.name==\"gosu-'$(dpkg --print-architecture)'\") | .browser_download_url' \
)\" && chmod +x ./gosu"]
COPY ./entrypoint.sh ./entrypoint
RUN chmod +x ./entrypoint
# UPPERDIR and WORKDIR **MUST BE ON THE SAME FILESYSTEM**, so
# instead of creating a VOLUME for UPPERDIR we have to create a
# parent directory for both UPPERDIR and WORKDIR, and then make
# it the VOLUME.
RUN ["/bin/bash", "-c", "mkdir -p /var/overlay-test/{lower,upper/{data,work}} /mnt/overlay-test"]
VOLUME /var/overlay-test/upper
# Create a file named FOO in the lower/root branch
RUN touch /var/overlay-test/lower/FOO
ENTRYPOINT ["entrypoint"]
<强> ./entrypoint.sh
强>:
#!/bin/bash
set -e
cd /var/overlay-test
mount -t overlay -o lowerdir=lower,upperdir=upper/data,workdir=upper/work overlay /mnt/overlay-test
chown -R "$DUID":"$DGID" ./
chown root: ./upper/work
chmod 0750 ./upper/work
cd /mnt/overlay-test
exec gosu "$DUID":"$DGID" $@
host$
docker build -t overlay-test ./
Successfully built 582352b90f53
好的,让我们测试吧!
注意:在Ubuntu 15.04主机下,我无法通过容器内的安装目录删除(覆盖whiteout)lowerdir
中存在的所有文件。这个bug似乎是罪魁祸首:
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1480411 - 编辑:rm
突然工作,我可以在upper/data
中看到char文件,所以我只能假设这是固定的,并且我收到了更新的包。
host$
docker run -it --name = overlay-test --env =&#34; DUID = $(id -u)&#34; --env =&#34; DGID = $(id -g)&#34; --cap-add = SYS_ADMIN --security-opt = apparmor:unconfined overlay-test / bin / bash
<强> overlay-test$
强> ID
uid=1000 gid=1000 groups=1000
overlay-test$
mount | grep&#39; / mnt / overlay-test&#39;
overlay on /mnt/overlay-test type overlay (rw,relatime,lowerdir=lower,upperdir=upper/data,workdir=upper/work)
<强> overlay-test$
强> PWD
/mnt/overlay-test
overlay-test$
ls -Al | sed&#39; / ^ t / d&#39;
-rw-r--r-- 1 1000 1000 0 Oct 24 03:54 FOO
overlay-test$
触摸BAR
overlay-test$
ls -Al | sed&#39; / ^ t / d&#39;
-rw-r--r-- 1 1000 1000 0 Oct 24 04:21 BAR -rw-r--r-- 1 1000 1000 0 Oct 24 03:54 FOO
overlay-test$
ls -Al / var / overlay-test / {lower /,upper / *} | sed&#39; / ^ t / d&#39;
ls: cannot open directory /var/overlay-test/upper/work: Permission denied
/var/overlay-test/lower:
-rw-r--r-- 1 1000 1000 0 Oct 24 03:54 FOO
/var/overlay-test/upper/data:
-rw-r--r-- 1 1000 1000 0 Oct 24 04:21 BAR
到目前为止一直这么好......让我们尝试从另一个容器中导入卷:
<强> overlay-test$
强> 出口
host$
docker run --rm --user =&#34; $(id -u):$(id -g)&#34; --volumes-from = overlay-test debian:jessie / bin / bash -c&#34; ls -Al / var / overlay-test / upper / * | sed&#39; / ^ t / d&#39;&#34;
ls: cannot open directory /var/overlay-test/upper/work: Permission denied
/var/overlay-test/upper/data:
-rw-r--r-- 1 1000 1000 0 Oct 24 05:32 BAR
成功!请注意,您还可以在RUN echo
中>> /etc/fstab
安装规范Dockerfile
,然后在入口点脚本中mount -a
,但根据我的经验,这种方法很奇怪。我不确定原因,但由于两种方法之间没有功能差异,我没有进一步调查。
清理: host$
docker rm -v overlay-test&amp;&amp; docker rmi overlay-test
Docker中容器运行时安全性的文档:
https://docs.docker.com/reference/run/#security-configuration https://docs.docker.com/reference/run/#runtime-privilege-linux-capabilities-and-lxc-configuration