简体   繁体   English

我可以在Docker Alpine容器中使用“ mount”吗?

[英]Can I use “mount” inside a Docker Alpine container?

I am Dockerising an old project. 我正在Docker一个旧项目。 A feature in the project pulls in user-specified Git repos, and since the size of a repo could cause the filing system to be overwhelmed, I created a local filing system of a fixed size, and then mounted it. 该项目中的一个功能引入了用户指定的Git仓库,并且由于仓库的大小可能导致文件系统不堪重负,因此我创建了一个固定大小的本地文件系统,然后安装了它。 This was intended to prevent the web host from having its file system filled up. 这样做是为了防止Web主机填充其文件系统。

The general approach is this: 通用方法是这样的:

IMAGE=filesystem/image.img
MOUNT_POINT=filesystem/mount
SIZE=20
PROJECT_ROOT=`pwd`

# Number of M to set aside for this filing system
dd if=/dev/zero of=$IMAGE bs=1M count=$SIZE &> /dev/null

# Format: the -F permits creation even though it's not a "block special device"
mkfs.ext3 -F -q $IMAGE

# Mount if the filing system is not already mounted
$MOUNTCMD | cut -d ' ' -f 3 | grep -q "^${PROJECT_ROOT}/${MOUNT_POINT}$"
if [ $? -ne 0 ]; then
    # -p Create all parent dirs as necessary
    mkdir -p $MOUNT_POINT
    /bin/mount -t ext3 $IMAGE $MOUNT_POINT
fi

This works fine in a Linux local or remote VM. 这在Linux本地或远程VM上运行良好。 However, I'd like to run this shell code, or something like it, inside a container. 但是,我想容器中运行此Shell代码或类似的代码。 Part of the reason I'd like to do that is to contain all fiddly stuff inside a container, so that building a new host machine is as kept as simple as possible (in my view, setting up custom mounts and cron-restart rules on the host works against that). 我想要这样做的部分原因是将所有杂物包含在容器中,以便尽可能简化构建新主机的过程(在我看来,在上设置自定义安装和cron-restart规则主机对此表示反对)。

So, this command does not work inside a container ("filesystem" is an on-host Docker volume) 因此,此命令在容器内不起作用(“文件系统”是主机上的Docker卷)

mount -t ext3 filesystem/image.img filesystem/mount
mount: can't setup loop device: No space left on device

It also does not work on a container folder ("filesystem2" is a container directory): 它也不适用于容器文件夹(“ filesystem2”是容器目录):

dd if=/dev/zero of=filesystem2/image.img bs=1M count=20
mount -t ext3 filesystem2/image.img filesystem2/mount
mount: can't setup loop device: No space left on device

I wonder whether containers just don't have the right internal machinery to do mounting, and thus whether I should change course. 我想知道容器是否没有正确的内部机械来进行安装,因此我是否应该改变路线。 I'd prefer not to spend too much time on this (I'm just moving a project to a Docker-only server) which is why I would like to get mount working if I can. 我不希望在此上花费太多时间(我只是将项目移到仅Docker的服务器上),这就是为什么我想尽可能地使mount工作。

Other options 其他选择

If that's not possible, then a size-limited Docker volume, that works with both Docker and Swarm, may be an alternative I'd need to look into. 如果那不可能,那么我需要研究一个既可用于Docker又可用于Swarm的大小受限制的Docker卷。 There are conflicting reports on the web as to whether this actually works ( see this question ). 关于此功能是否确实有效,网络上有相互矛盾的报告( 请参阅此问题 )。

There is a suggestion here to say this is supported in Flocker. 这里有一个建议可以说这是Flocker支持的。 However, I am hesitant to use that, as it appears to be abandoned , presumably having been affected by ClusterHQ going bust. 但是,我很犹豫地使用它,因为它似乎已被废弃 ,大概已经受到ClusterHQ破产的影响。

This post indicates I can use --storage-opt size=120G with docker run . 这篇文章表示我可以使用--storage-opt size=120Gdocker run However, it does not look like it is supported by docker service create (unless perhaps the option has been renamed). 但是,它似乎并不受docker service create支持(除非该选项已重命名)。

Update 更新资料

As per the comment convo, I made some progress; 根据评论专栏,我取得了一些进展; I found that adding --privileged to the docker run enables mounting, at the cost of removing security isolation. 我发现将--privileged添加到--privileged docker run可以启用挂载,但要以删除安全隔离为代价。 A helpful commenter says that it is better to use the more fine-grained control of --cap-add SYS_ADMIN , allowing the container to retain some of its isolation. 一位有用的评论者说,最好使用--cap-add SYS_ADMIN的更细粒度的控件,使容器保留一些隔离。

However, Docker Swarm has not yet implemented either of these flags, so I can't use this solution. 但是,Docker Swarm尚未实现这两个标志中的任何一个,因此我无法使用此解决方案。 This lengthy feature request suggests to me that this feature is not going to be added in a hurry; 这个冗长的功能请求向我建议不要急着添加此功能。 it's been pending for two years already. 它已经待了两年了。

I have found a size-limiting solution I am happy with, and it does not use the Linux mount command at all. 我找到了一个我满意的大小限制解决方案,它根本不使用Linux mount命令。 I've not implemented it yet, but the tests documented below are satisfying enough. 我还没有实现它,但是下面记录的测试已经足够令人满意。 Readers may wish to note the minor warnings at the end. 读者不妨注意最后的小警告。

I had not tried mounting Docker volumes prior to asking this question, since part of my research stumbled on a Stack Overflow poster casting doubt on whether Docker volumes can be made to respect a size limitation. 在问这个问题之前,我没有尝试安装Docker卷,因为我的研究的一部分偶然发现了Stack Overflow海报,使人们怀疑是否可以制作Docker卷来遵守大小限制。 My test indicates that they can, but you may wish to test this on your own platform to ensure it works for you. 我的测试表明他们可以,但是您可能希望在自己的平台上对其进行测试,以确保它适合您。

Size limit on Docker container Docker容器的大小限制

The below commands have been cobbled together from various sources on the web. 以下命令已从网络上的各种来源整理而来。

To start with, I create a volume like so, with a 20m size limit: 首先,我创建一个像这样的卷,大小限制为20m:

docker volume create \
    --driver local \
    --opt o=size=20m \
    --opt type=tmpfs \
    --opt device=tmpfs \
    hello-volume

I then create an Alpine Swarm service with a mount on this container: 然后,我在该容器上创建带有挂载的Alpine Swarm服务:

docker service create \
    --mount source=hello-volume,target=/myvol \
    alpine \
    sleep 10000

We can ensure the container is mounted by getting a shell on the single container in this service: 通过在此服务中的单个容器上获得外壳,我们可以确保容器已安装:

docker exec -it amazing_feynman.1.lpsgoyv0jrju6fvb8skrybqap
/ # ls - /myvol
total 0

OK, great. 好,很好。 So, while remaining in this shell, let's try slowly overwhelming this disk, in 5m increments. 因此,在保留在此外壳中的同时,让我们尝试以5m的增量缓慢压倒该磁盘。 We can see that it fails on the fifth try, which is what we would expect: 我们可以看到它在第五次尝试时失败了,这是我们期望的:

/ # cd /myvol
/myvol # ls
/myvol # dd if=/dev/zero of=image1 bs=1M count=5
5+0 records in
5+0 records out
/myvol # dd if=/dev/zero of=image2 bs=1M count=5
5+0 records in
5+0 records out
/myvol # ls -l
total 10240
-rw-r--r--    1 root     root       5242880 Sep 16 13:11 image1
-rw-r--r--    1 root     root       5242880 Sep 16 13:12 image2
/myvol # dd if=/dev/zero of=image3 bs=1M count=5
5+0 records in
5+0 records out
/myvol # dd if=/dev/zero of=image4 bs=1M count=5
5+0 records in
5+0 records out
/myvol # ls -l
total 20480
-rw-r--r--    1 root     root       5242880 Sep 16 13:11 image1
-rw-r--r--    1 root     root       5242880 Sep 16 13:12 image2
-rw-r--r--    1 root     root       5242880 Sep 16 13:12 image3
-rw-r--r--    1 root     root       5242880 Sep 16 13:12 image4
/myvol # dd if=/dev/zero of=image5 bs=1M count=5
dd: writing 'image5': No space left on device
1+0 records in
0+0 records out
/myvol # 

Finally, let's see if we can get an error by overwhelming the disk in one go, in case the limitation only applies to newly opened file handles in a full disk: 最后,看看该限制是否仅适用于已满的磁盘中新打开的文件句柄,是否可以通过一次压倒磁盘来获取错误:

/ # cd /myvol
/ # rm *
/myvol # dd if=/dev/zero of=image1 bs=1M count=21
dd: writing 'image1': No space left on device
21+0 records in
20+0 records out

It turns out we can, so that looks pretty robust to me. 事实证明我们可以,所以对我来说看起来很强大。

Nota bene Nota bene

The volume is created with a type and a device of "tmpfs", which sounded to me worryingly like a RAM disk. 该卷是用“ tmpfs”的typedevice创建的,在我看来,这听起来像是RAM磁盘。 I've successfully checked that the volume remains connected and intact after a system reboot, so it looks good to me, at least for now. 我已经成功地检查了卷,并在系统重新引导后保持了连接状态并保持完好无损,因此至少对我来说看起来不错。

However, I'd say that when it comes to organising your data persistence systems, don't just copy what I have. 但是,我要说的是,在组织数据持久性系统时,不仅要复制我拥有的内容。 Make sure the volume is robust enough for your use case before you put it into production, and of course, make sure you include it in your back-up process. 在将其投入生产之前,请确保该卷对于您的用例而言足够坚固,当然,请确保将其包括在备份过程中。

(This is for Docker version 18.06.1-ce, build e68fc7a). (这是针对Docker 18.06.1-ce版本,内部版本e68fc7a)。

You won't be able to safely do this inside of a container. 您将无法在容器内安全地执行此操作。 Docker removes the mount privilege from containers because using this you could mount the host filesystem and escape the container. Docker会从容器中删除安装特权,因为使用该特权您可以安装主机文件系统并转出容器。 However, you can do this outside of the container and mount the filesystem into the container as a volume using the default local driver. 但是,您可以在容器外部执行此操作,然后使用默认的本地驱动程序将文件系统作为卷挂载到容器中。 The size option isn't supported by most filesystems, tmpfs being one of the few exceptions. 大多数文件系统不支持size选项,tmpfs是少数例外之一。 Most of them use the size of the underlying device which you defined with the image file creation command: 它们中的大多数使用您通过映像文件创建命令定义的基础设备的大小:

dd if=/dev/zero of=filesystem/image.img bs=1M count=$SIZE

I had trouble getting docker to create the loop device dynamically, so here's the process to create it manually: 我在让docker动态创建循环设备方面遇到了麻烦,因此这是手动创建它的过程:

$ sudo losetup --find --show ./vol-image.img
/dev/loop0
$ sudo mkfs -t ext3 /dev/loop0
mke2fs 1.43.4 (31-Jan-2017)
Creating filesystem with 10240 1k blocks and 2560 inodes
Filesystem UUID: 25c95fcd-6c78-4b8e-b923-f808517b28df
Superblock backups stored on blocks:
        8193

Allocating group tables: done
Writing inode tables: done
Creating journal (1024 blocks): done
Writing superblocks and filesystem accounting information: done

When defining the volume mount options are passed almost verbatim from the mount command you run on the command line: 定义卷挂载选项时,几乎逐行传递您在命令行上运行的mount命令:

docker volume create --driver local --opt type=ext3 \
  --opt device=filesystem/image.img app_vol
docker service create --mount type=volume,src=app_vol,dst=/filesystem/mount ...

or in a single service create command: 或在单个服务中创建命令:

docker service create \
  --mount type=volume,src=app_vol,dst=/filesystem/mount,volume-driver=local,volume-opt=type=ext3,volume-opt=device=filesystem/image.img ...

With docker run , the command looks like: 使用docker run ,命令如下所示:

$ docker run -it --rm --mount type=volume,dst=/data,src=ext3vol,volume-driver=local,volume-opt=type=ext3,volume-opt=device=/dev/loop0 busybox /bin/sh
/ # ls -al /data
total 17
drwxr-xr-x    3 root     root          1024 Sep 19 14:39 .
drwxr-xr-x    1 root     root          4096 Sep 19 14:40 ..
drwx------    2 root     root         12288 Sep 19 14:39 lost+found

The only prerequisite is that you create this file and loop device before creating the service, and that this file is accessible wherever the service is scheduled. 唯一的先决条件是在创建服务之前创建此文件和循环设备,并且无论计划了什么服务都可以访问此文件。 I would also suggest making all of the paths in these commands fully qualified rather than relative to the current directory. 我还建议使这些命令中的所有路径完全合格,而不要相对于当前目录。 I'm pretty sure there are a few places that relative paths don't work. 我很确定在某些地方相对路径不起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM