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

时间:2021-09-26 07:15:16

I can't understand why the 'chown' command should increase the size of my docker image?

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

The following Dockerfile creates an image of size 5.3MB:

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

FROM alpine:edge
RUN adduser example -D -h /example -s /bin/sh

This example however creates an image of size 8.7MB:

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

FROM alpine:edge
RUN adduser example -D -h /example -s /bin/sh && \
    chown -R example.example /lib

Why?

Note: My actual dockerfile is of course much longer than this example and therefore the increase in image size is also quite larger. That's why I even care..

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

4 个解决方案

#1


Every step in a Dockerfile generates a new intermediate image, or "layer", consisting of anything that changed on the filesystem from the previous layer. A docker image consists of a collection of layers that are applied one on top of another to create the final filesystem.

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

If you have:

如果你有:

RUN adduser example -D -h /example -s /bin/sh

Then you are probably changing nothing other than a few files in /etc (/etc/passwd, /etc/group, and their shadow equivalents).

那你除了/ etc(/ etc / passwd,/ etc / group和它们的阴影等价物)中的一些文件之外什么都没有改变。

If you have:

如果你有:

RUN adduser example -D -h /example -s /bin/sh && \
    chown -R example.example /lib

Then the list of things that have changed includes, recursively, everything in /lib, which is potentially larger. In fact, in my alpine:edge container, it looks like the contents of /lib is 3.4MB:

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

/ # du -sh /lib
3.4M    /lib

Which exactly accounts for the change in image size in your example.

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

UPDATE

Using your actual Dockerfile, with the npm install ... line commented out, I don't see any difference in the final image size whether or not the adduser and chown commands are run. Given:

使用实际的Dockerfile,npm install ...行注释掉,无论是否运行adduser和chown命令,我都看不出最终图像大小有任何差异。鉴于:

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/*

I get:

$ docker build -t sotest .
[...]
Successfully built 058d9f41988a
$ docker inspect -f '{{.VirtualSize}}' 058d9f41988a
31783340

Whereas given:

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/*

I get:

$ docker build -t sotest .
[...]
Successfully built 696b481c5790
$ docker inspect -f '{{.VirtualSize}}' 696b481c5790
31789262

That is, the two images are approximately the same size (the difference is around 5 Kb).

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

I would of course expect the resulting image to be larger if the npm install command could run successfully (because that would install additional files).

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

#2


This is a known problem unfortunately: https://github.com/docker/docker/issues/5505 and https://github.com/docker/docker/issues/6119#issuecomment-70606158

遗憾的是,这是一个已知问题:https://github.com/docker/docker/issues/5505和https://github.com/docker/docker/issues/6119#issuecomment-70606158

You can fix this by changing the docker storage driver from aufs to devicemapper as described in https://github.com/docker/docker/issues/6119#issuecomment-268870519

您可以通过将docker存储驱动程序从aufs更改为devicemapper来解决此问题,如https://github.com/docker/docker/issues/6119#issuecomment-268870519中所述

#3


Now you can inspect your image & its layers visually using ImageLayers.io to help see why the extra size is.

现在,您可以使用ImageLayers.io直观地检查图像及其图层,以帮助查看额外尺寸的原因。

also, docker history shows similar stuff.

此外,码头历史显示类似的东西。

#4


Since Docker 17.09 one can use --chown flag on ADD/COPY operations in Dockerfile to change the owner in the ADD/COPY step itself rather than a separate RUN operation with chown which increases the size of the image as you have noted. It would have been good to have this as the default mode i.e. the permissions of the user copying the files are applied to the copied files. However, the Docker team did not want to break backward compatibility and hence introduced a new flag.

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

COPY --chown=:

The other alternatives are: 1. Change the permission in a staging folder prior to building the image.

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

  1. Run the container via a bootstrap script that changes the ownership.

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

  2. Squash the layers!

    压制图层!

#1


Every step in a Dockerfile generates a new intermediate image, or "layer", consisting of anything that changed on the filesystem from the previous layer. A docker image consists of a collection of layers that are applied one on top of another to create the final filesystem.

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

If you have:

如果你有:

RUN adduser example -D -h /example -s /bin/sh

Then you are probably changing nothing other than a few files in /etc (/etc/passwd, /etc/group, and their shadow equivalents).

那你除了/ etc(/ etc / passwd,/ etc / group和它们的阴影等价物)中的一些文件之外什么都没有改变。

If you have:

如果你有:

RUN adduser example -D -h /example -s /bin/sh && \
    chown -R example.example /lib

Then the list of things that have changed includes, recursively, everything in /lib, which is potentially larger. In fact, in my alpine:edge container, it looks like the contents of /lib is 3.4MB:

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

/ # du -sh /lib
3.4M    /lib

Which exactly accounts for the change in image size in your example.

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

UPDATE

Using your actual Dockerfile, with the npm install ... line commented out, I don't see any difference in the final image size whether or not the adduser and chown commands are run. Given:

使用实际的Dockerfile,npm install ...行注释掉,无论是否运行adduser和chown命令,我都看不出最终图像大小有任何差异。鉴于:

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/*

I get:

$ docker build -t sotest .
[...]
Successfully built 058d9f41988a
$ docker inspect -f '{{.VirtualSize}}' 058d9f41988a
31783340

Whereas given:

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/*

I get:

$ docker build -t sotest .
[...]
Successfully built 696b481c5790
$ docker inspect -f '{{.VirtualSize}}' 696b481c5790
31789262

That is, the two images are approximately the same size (the difference is around 5 Kb).

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

I would of course expect the resulting image to be larger if the npm install command could run successfully (because that would install additional files).

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

#2


This is a known problem unfortunately: https://github.com/docker/docker/issues/5505 and https://github.com/docker/docker/issues/6119#issuecomment-70606158

遗憾的是,这是一个已知问题:https://github.com/docker/docker/issues/5505和https://github.com/docker/docker/issues/6119#issuecomment-70606158

You can fix this by changing the docker storage driver from aufs to devicemapper as described in https://github.com/docker/docker/issues/6119#issuecomment-268870519

您可以通过将docker存储驱动程序从aufs更改为devicemapper来解决此问题,如https://github.com/docker/docker/issues/6119#issuecomment-268870519中所述

#3


Now you can inspect your image & its layers visually using ImageLayers.io to help see why the extra size is.

现在,您可以使用ImageLayers.io直观地检查图像及其图层,以帮助查看额外尺寸的原因。

also, docker history shows similar stuff.

此外,码头历史显示类似的东西。

#4


Since Docker 17.09 one can use --chown flag on ADD/COPY operations in Dockerfile to change the owner in the ADD/COPY step itself rather than a separate RUN operation with chown which increases the size of the image as you have noted. It would have been good to have this as the default mode i.e. the permissions of the user copying the files are applied to the copied files. However, the Docker team did not want to break backward compatibility and hence introduced a new flag.

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

COPY --chown=:

The other alternatives are: 1. Change the permission in a staging folder prior to building the image.

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

  1. Run the container via a bootstrap script that changes the ownership.

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

  2. Squash the layers!

    压制图层!