[英]Can I use “mount” inside a Docker Alpine container?
我正在Docker一個舊項目。 該項目中的一個功能引入了用戶指定的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-restart規則主機對此表示反對)。
因此,此命令在容器內不起作用(“文件系統”是主機上的Docker卷)
mount -t ext3 filesystem/image.img filesystem/mount
mount: can't setup loop device: No space left on device
它也不適用於容器文件夾(“ 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
我想知道容器是否沒有正確的內部機械來進行安裝,因此我是否應該改變路線。 我不希望在此上花費太多時間(我只是將項目移到僅Docker的服務器上),這就是為什么我想盡可能地使mount
工作。
如果那不可能,那么我需要研究一個既可用於Docker又可用於Swarm的大小受限制的Docker卷。 關於此功能是否確實有效,網絡上有相互矛盾的報告( 請參閱此問題 )。
這里有一個建議可以說這是Flocker支持的。 但是,我很猶豫地使用它,因為它似乎已被廢棄 ,大概已經受到ClusterHQ破產的影響。
這篇文章表示我可以使用--storage-opt size=120G
與docker run
。 但是,它似乎並不受docker service create
支持(除非該選項已重命名)。
根據評論專欄,我取得了一些進展; 我發現將--privileged
添加到--privileged
docker run
可以啟用掛載,但要以刪除安全隔離為代價。 一位有用的評論者說,最好使用--cap-add SYS_ADMIN
的更細粒度的控件,使容器保留一些隔離。
但是,Docker Swarm尚未實現這兩個標志中的任何一個,因此我無法使用此解決方案。 這個冗長的功能請求向我建議不要急着添加此功能。 它已經待了兩年了。
我找到了一個我滿意的大小限制解決方案,它根本不使用Linux mount
命令。 我還沒有實現它,但是下面記錄的測試已經足夠令人滿意。 讀者不妨注意最后的小警告。
在問這個問題之前,我沒有嘗試安裝Docker卷,因為我的研究的一部分偶然發現了Stack Overflow海報,使人們懷疑是否可以制作Docker卷來遵守大小限制。 我的測試表明他們可以,但是您可能希望在自己的平台上對其進行測試,以確保它適合您。
以下命令已從網絡上的各種來源整理而來。
首先,我創建一個像這樣的卷,大小限制為20m:
docker volume create \
--driver local \
--opt o=size=20m \
--opt type=tmpfs \
--opt device=tmpfs \
hello-volume
然后,我在該容器上創建帶有掛載的Alpine Swarm服務:
docker service create \
--mount source=hello-volume,target=/myvol \
alpine \
sleep 10000
通過在此服務中的單個容器上獲得外殼,我們可以確保容器已安裝:
docker exec -it amazing_feynman.1.lpsgoyv0jrju6fvb8skrybqap
/ # ls - /myvol
total 0
好,很好。 因此,在保留在此外殼中的同時,讓我們嘗試以5m的增量緩慢壓倒該磁盤。 我們可以看到它在第五次嘗試時失敗了,這是我們期望的:
/ # 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”的type
和device
創建的,在我看來,這聽起來像是RAM磁盤。 我已經成功地檢查了卷,並在系統重新引導后保持了連接狀態並保持完好無損,因此至少對我來說看起來不錯。
但是,我要說的是,在組織數據持久性系統時,不僅要復制我擁有的內容。 在將其投入生產之前,請確保該卷對於您的用例而言足夠堅固,當然,請確保將其包括在備份過程中。
(這是針對Docker 18.06.1-ce版本,內部版本e68fc7a)。
您將無法在容器內安全地執行此操作。 Docker會從容器中刪除安裝特權,因為使用該特權您可以安裝主機文件系統並轉出容器。 但是,您可以在容器外部執行此操作,然后使用默認的本地驅動程序將文件系統作為卷掛載到容器中。 大多數文件系統不支持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
定義卷掛載選項時,幾乎逐行傳遞您在命令行上運行的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 ...
或在單個服務中創建命令:
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
唯一的先決條件是在創建服務之前創建此文件和循環設備,並且無論計划了什么服務都可以訪問此文件。 我還建議使這些命令中的所有路徑完全合格,而不要相對於當前目錄。 我很確定在某些地方相對路徑不起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.