我可以用“吗?”;山;在Docker Alpine集装箱内?

我可以用“吗?”;山;在Docker Alpine集装箱内?,docker,sh,mount,alpine,Docker,Sh,Mount,Alpine,我正在做一个老项目。该项目中的一个特性引入了用户指定的Git回购协议,由于回购协议的大小可能会导致归档系统不堪重负,我创建了一个固定大小的本地归档系统,然后安装了它。这是为了防止web主机的文件系统被填满 一般做法如下: 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

我正在做一个老项目。该项目中的一个特性引入了用户指定的Git回购协议,由于回购协议的大小可能会导致归档系统不堪重负,我创建了一个固定大小的本地归档系统,然后安装了它。这是为了防止web主机的文件系统被填满

一般做法如下:

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
这在Linux本地或远程VM中运行良好。但是,我希望在容器中运行这个shell代码或类似的代码。我希望这样做的部分原因是将所有精细的东西都包含在一个容器中,以便构建一个新的主机尽可能简单(在我看来,在主机上设置自定义挂载和cron重启规则是与此相反的)

因此,此命令在容器中不起作用(“文件系统”是主机Docker卷上的文件系统)

它也不适用于容器文件夹(“filesystem2”是容器目录):

我想知道集装箱是否没有合适的内部机械来安装,因此我是否应该改变路线。我不想在这上面花费太多时间(我只是把一个项目转移到一个只支持Docker的服务器上),这就是为什么如果可以的话,我想让
mount
工作的原因

其他选择 如果这是不可能的,那么一个大小有限的Docker卷,可以与Docker和Swarm一起使用,可能是我需要研究的另一个选择。关于这是否真的有效,web上有相互矛盾的报告()

有一种说法是,这在Flocker中得到了支持。然而,我很犹豫是否使用它,因为它似乎受到ClusterHQ破产的影响

表示我可以将
--storage opt size=120G
docker run
一起使用。但是,
docker service create
似乎不支持该选项(除非该选项已重命名)

更新 根据车队的评论,我取得了一些进展;我发现将
--privileged
添加到
docker run
中可以进行装载,但代价是删除安全隔离。一位有帮助的评论者说,最好使用
——capaddsys_ADMIN
的更细粒度控制,允许容器保留一些隔离


然而,Docker Swarm还没有实现这两个标志,所以我不能使用这个解决方案。对我来说,这项功能不会很快添加;它已经挂起两年了。

我找到了一个我很满意的大小限制解决方案,它根本不使用Linux
mount
命令。我还没有实现它,但是下面记录的测试已经足够令人满意了。读者可能希望注意结尾处的小警告

在提出这个问题之前,我还没有尝试过安装Docker卷,因为我的部分研究偶然发现了一张堆栈溢出海报,这让我怀疑Docker卷是否可以按照大小限制制作。我的测试表明他们可以,但您可能希望在您自己的平台上进行测试,以确保它适合您

Docker容器的大小限制 以下命令是从web上的各种来源拼凑而成的

首先,我创建了一个大小限制为20m的卷:

docker volume create \
    --driver local \
    --opt o=size=20m \
    --opt type=tmpfs \
    --opt device=tmpfs \
    hello-volume
然后,我创建了一个阿尔卑斯Swarm服务,在这个容器上安装了一个挂载:

docker service create \
    --mount source=hello-volume,target=/myvol \
    alpine \
    sleep 10000
我们可以通过在该服务中的单个容器上获取外壳来确保容器已安装:

docker exec -it amazing_feynman.1.lpsgoyv0jrju6fvb8skrybqap
/ # ls - /myvol
total 0
好的,太好了。所以,在保持在这个外壳中的同时,让我们尝试以5百万的增量慢慢地覆盖这个磁盘。我们可以看到,它在第五次尝试时失败了,这是我们所期望的:

/ # 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 # 
最后,让我们看看,如果限制仅适用于完整磁盘中新打开的文件句柄,是否可以通过一次性覆盖磁盘来获得错误:

/ # 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
事实证明我们可以,所以我觉得这很有说服力

诺塔贝尼酒店 这个音量是用一个
类型
和一个
设备
的“tmpfs”创建的,我很担心这听起来像一个RAM磁盘。我已经成功地检查了该卷在系统重新启动后是否保持连接和完整性,因此至少目前来看,它看起来不错

然而,我要说的是,当涉及到组织数据持久性系统时,不要只是复制我所拥有的。在将其投入生产之前,确保该卷足够健壮,适合您的用例,当然,确保将其包括在备份过程中


(这适用于Docker版本18.06.1-ce,版本e68fc7a)。

您将无法在容器内安全地执行此操作。Docker从容器中删除mount特权,因为使用它可以挂载主机文件系统并转义容器。但是,您可以在容器外部执行此操作,并使用默认的本地驱动程序将文件系统作为卷装载到容器中。大多数文件系统不支持size选项,tmpfs是少数例外之一。它们中的大多数使用您使用图像文件创建命令定义的基础设备的大小:

dd if=/dev/zero of=filesystem/image.img bs=1M count=$SIZE
我很难让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
定义卷装载选项时,几乎是通过在命令行上运行的装载命令逐字传递的:

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 ...
或在单个服务创建命令中:

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 ...
使用
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

唯一的先决条件是,您必须在创建服务之前创建此文件并循环设备,并且可以在计划服务的任何位置访问此文件。我还建议将这些命令中的所有路径完全限定,而不是相对于当前目录。我很确定有几个地方相对路径不起作用。

啊,我刚刚在Ubuntu容器中安装了一个文件,带有
--privileged
。现在,我只需要在服务中这样做,但这是不允许的;解决方法是。您可以允许
m
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 ...
$ 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