为什么chown会增加docker图像的大小?

Fra*_*alf 7 filesize chown docker dockerfile

我不明白为什么'chown'命令会增加我的docker图像的大小?

以下Dockerfile创建大小为5.3MB的图像:

FROM alpine:edge
RUN adduser example -D -h /example -s /bin/sh
Run Code Online (Sandbox Code Playgroud)

但是,此示例创建了一个大小为8.7MB的图像:

FROM alpine:edge
RUN adduser example -D -h /example -s /bin/sh && \
    chown -R example.example /lib
Run Code Online (Sandbox Code Playgroud)

为什么?

注意:我的实际dockerfile当然比这个例子长得多,因此图像大小的增加也相当大.这就是我甚至关心的原因..

lar*_*sks 9

Dockerfile中的每一步都会生成一个新的中间图像或"图层",由前一层文件系统上发生的任何变化组成.docker镜像由一组图层组成,这些图层一个在另一个上面应用,以创建最终的文件系统.

如果你有:

RUN adduser example -D -h /example -s /bin/sh
Run Code Online (Sandbox Code Playgroud)

那么你可能改变不外乎几个文件等在/etc(/etc/passwd,/etc/group,和他们的影子当量).

如果你有:

RUN adduser example -D -h /example -s /bin/sh && \
    chown -R example.example /lib
Run Code Online (Sandbox Code Playgroud)

然后,已经更改的事物列表包括递归地包含的所有内容/lib,这些内容可能更大.事实上,在我的alpine:edge容器中,它的内容看起来像是/lib3.4MB:

/ # du -sh /lib
3.4M    /lib
Run Code Online (Sandbox Code Playgroud)

这恰恰说明了示例中图像大小的变化.

UPDATE

使用您的实际Dockerfile,在npm install ...注释掉的行中,无论是否运行adduserchown命令,我都看不到最终图像大小的任何差异.鉴于:

RUN echo "http://nl.alpinelinux.org/alpine/edge/main" > /etc/apk/repositories && \
    echo "http://nl.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
    apk add -U wget iojs && \
    apk upgrade && \
    wget -q --no-check-certificate https://ghost.org/zip/ghost-0.6.0.zip -O /tmp/ghost.zip && \
    unzip -q /tmp/ghost.zip -d /ghost && \
    cd /ghost && \
#    npm install --production && \
    sed 's/127.0.0.1/0.0.0.0/' /ghost/config.example.js > /ghost/config.js && \
    sed -i 's/"iojs": "~1.2.0"/"iojs": "~1.6.4"/' package.json && \
#   adduser ghost -D -h /ghost -s /bin/sh && \
#   chown -R ghost.ghost * && \
    npm cache clean && \
    rm -rf /var/cache/apk/* /tmp/*
Run Code Online (Sandbox Code Playgroud)

我明白了:

$ docker build -t sotest .
[...]
Successfully built 058d9f41988a
$ docker inspect -f '{{.VirtualSize}}' 058d9f41988a
31783340
Run Code Online (Sandbox Code Playgroud)

鉴于:

RUN echo "http://nl.alpinelinux.org/alpine/edge/main" > /etc/apk/repositories && \
    echo "http://nl.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
    apk add -U wget iojs && \
    apk upgrade && \
    wget -q --no-check-certificate https://ghost.org/zip/ghost-0.6.0.zip -O /tmp/ghost.zip && \
    unzip -q /tmp/ghost.zip -d /ghost && \
    cd /ghost && \
#    npm install --production && \
    sed 's/127.0.0.1/0.0.0.0/' /ghost/config.example.js > /ghost/config.js && \
    sed -i 's/"iojs": "~1.2.0"/"iojs": "~1.6.4"/' package.json && \
    adduser ghost -D -h /ghost -s /bin/sh && \
    chown -R ghost.ghost * && \
    npm cache clean && \
    rm -rf /var/cache/apk/* /tmp/*
Run Code Online (Sandbox Code Playgroud)

我明白了:

$ docker build -t sotest .
[...]
Successfully built 696b481c5790
$ docker inspect -f '{{.VirtualSize}}' 696b481c5790
31789262
Run Code Online (Sandbox Code Playgroud)

也就是说,两个图像的大小大致相同(差异大约为5 Kb).

如果npm install命令可以成功运行(因为那会安装其他文件),我当然希望得到的图像更大.


Vin*_*ari 9

从 Docker 17.09 开始,可以在 Dockerfile 中的 ADD/COPY 操作上使用 --chown 标志来更改 ADD/COPY 步骤本身中的所有者,而不是使用 chown 进行单独的 RUN 操作,这会增加图像的大小,正如您所指出的。将此作为默认模式会很好,即将复制文件的用户的权限应用于复制的文件。但是,Docker 团队不想破坏向后兼容性,因此引入了一个新标志。

复制 --chown=:

其他替代方法是: 1. 在构建映像之前更改暂存文件夹中的权限。

  1. 通过更改所有权的引导脚本运行容器。

  2. 压扁层!