为什么使用`chmod`命令会导致`docker build`占用过多磁盘空间?

3

我的Docker构建基本完成,我只需要递归地执行chownchmod一个大目录。

以下是docker build的部分输出:

Step 34/40 : RUN du -b -m -s / 2>/dev/null || true
 ---> Running in d261dfc7a9f8
1537    /
Removing intermediate container d261dfc7a9f8
 ---> 663d129f1487
Step 35/40 : RUN df --si -m /;df -i /;
 ---> Running in 8249096d3069
Filesystem     1M-blocks  Used Available Use% Mounted on
overlay            29674 28609      1066  97% /
Filesystem           Inodes  IUsed   IFree IUse% Mounted on
overlay             2737520 549839 2187681   21% /
Removing intermediate container 8249096d3069
 ---> fc4250e3433d
Step 36/40 : RUN chmod -R a+rwX /var/www/html
 ---> Running in 2705265de405
Error processing tar file(exit status 1): open /var/www/html/[...].php: no space left on device

我通过运行 docker system prune -a 解决了我的问题,释放了额外的908 MB,但我不明白为什么磁盘空间首先成为问题(更不用说 tar 与此有什么关系了...)。
运行 watch df -m /,我可以清楚地看到 chmod 导致几百MB的大幅波动(上升和下降),但这毫无意义,因为 chmod 不应该改变磁盘分配,即使是 CoW(写时复制)文件或稀疏文件。
为什么 dockers 实现的 chmod (我使用的是 FROM centos:7.4.1708)会导致额外的磁盘空间被使用?
2个回答

3

导致额外磁盘空间的原因不是chmod。在Dockerfile中,run命令会创建一个缓存层,这将占用您的磁盘空间。建议使用&&聚合运行的命令。


你不能将 COPY&& chmod 结合使用。相反,你可以使用 copy --chown - Roman Zagday

2
在docker中,文件系统层采用写时复制的解决方案实现。对文件所做的任何更改都会首先复制该文件,然后将更改应用于该文件副本,甚至是权限、所有者或时间戳。当递归运行chown和chmod命令时,即使未更改权限,时间戳也会更改。
因此,为了最小化docker中的层大小,请在同一层中进行所有文件更改。每个步骤都会创建一个新层,因此请将更改合并到同一步骤中。使用COPY命令,在源上修复权限并查看调整所有权的选项。使用RUN时,您经常会看到使用&&语法链接的命令以压缩为单个步骤。这在创建临时文件时特别重要,因为您需要在步骤完成之前删除它们,以避免将它们写入镜像层。

在我的系统上,写时复制文件的磁盘使用量不受权限、时间戳或追加数据的影响,磁盘使用量保持不变。我相信写时复制是在单个块级别而不是每个文件级别上完成的。 - user3338098
哦,我现在明白了,你是泛指“写时复制”,但我是指特定的cp --reflink=always意义上的“写时复制”。 - user3338098
@user3338098,Docker的写时复制取决于文件系统驱动程序(也称为图形驱动程序)。通常情况下,这是overlay2。当Dockerfile中的步骤之间发生更改时,即使只是权限更改,整个文件也会被复制。 - BMitch
幸运的是,现在的Docker已经对文件的访问时间戳等做出了过滤器的更改,但在将层打包为镜像之前,基础的overlay2文件系统仍然会发生写时复制。 - BMitch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接