为什么 chown 会增加 docker 图像的大小?
Why does chown increase size of docker image?
我不明白为什么 'chown' 命令会增加我的 docker 图片的大小?
以下 Dockerfile 创建一个大小为 5.3MB 的图像:
FROM alpine:edge
RUN adduser example -D -h /example -s /bin/sh
然而,此示例创建了一个大小为 8.7MB 的图像:
FROM alpine:edge
RUN adduser example -D -h /example -s /bin/sh && \
chown -R example.example /lib
为什么?
注意:我的实际docker文件当然比这个例子长很多,因此图像尺寸的增加也比较大。这就是为什么我什至关心..
Dockerfile 中的每一步都会生成一个新的中间映像,或 "layer",其中包含文件系统上从上一层发生的任何更改。 docker 图像由层的集合组成,层层叠加以创建最终的文件系统。
如果你有:
RUN adduser example -D -h /example -s /bin/sh
那么除了 /etc
中的几个文件(/etc/passwd
、/etc/group
以及它们的影子等价物)之外,您可能没有做任何更改。
如果你有:
RUN adduser example -D -h /example -s /bin/sh && \
chown -R example.example /lib
然后已更改的列表递归地包括 /lib
中的所有内容,这可能更大。事实上,在我的 alpine:edge
容器中, /lib
的内容看起来是 3.4MB:
/ # du -sh /lib
3.4M /lib
这正是您示例中图像大小变化的原因。
更新
使用您实际的 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/*
我得到:
$ docker build -t sotest .
[...]
Successfully built 058d9f41988a
$ docker inspect -f '{{.VirtualSize}}' 058d9f41988a
31783340
鉴于:
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/*
我得到:
$ docker build -t sotest .
[...]
Successfully built 696b481c5790
$ docker inspect -f '{{.VirtualSize}}' 696b481c5790
31789262
即两张图片大小差不多(
差异约为 5 Kb)。
如果 npm install
命令能够 运行 成功,我当然希望生成的图像更大(因为那样会安装额外的文件)。
现在您可以使用 ImageLayers.io 直观地检查您的图像及其图层,以帮助了解额外尺寸的原因。
另外,
docker 历史显示了类似的东西。
不幸的是,这是一个已知问题:https://github.com/docker/docker/issues/5505 and https://github.com/docker/docker/issues/6119#issuecomment-70606158
您可以通过将 docker 存储驱动程序从 aufs 更改为 devicemapper 来解决此问题,如 https://github.com/docker/docker/issues/6119#issuecomment-268870519
中所述
从 Docker 17.09 开始,可以在 Docker 文件中的 ADD/COPY 操作上使用 --chown
标志来更改 ADD/COPY 步骤本身的所有者而不是使用 chown 的单独 运行 操作,它会增加图像的大小,正如您所注意到的。最好将此作为默认模式,即复制文件的用户权限应用于复制的文件。但是,Docker 团队不想破坏向后兼容性,因此引入了一个新标志。
的文档中阅读更多内容
COPY --chown=<user>:<group> <hostPath> <containerPath>
其他备选方案是:
在构建映像之前更改暂存文件夹中的权限。
运行 通过 bootstrap 脚本更改所有权的容器。
压扁图层!
我不明白为什么 'chown' 命令会增加我的 docker 图片的大小?
以下 Dockerfile 创建一个大小为 5.3MB 的图像:
FROM alpine:edge
RUN adduser example -D -h /example -s /bin/sh
然而,此示例创建了一个大小为 8.7MB 的图像:
FROM alpine:edge
RUN adduser example -D -h /example -s /bin/sh && \
chown -R example.example /lib
为什么?
注意:我的实际docker文件当然比这个例子长很多,因此图像尺寸的增加也比较大。这就是为什么我什至关心..
Dockerfile 中的每一步都会生成一个新的中间映像,或 "layer",其中包含文件系统上从上一层发生的任何更改。 docker 图像由层的集合组成,层层叠加以创建最终的文件系统。
如果你有:
RUN adduser example -D -h /example -s /bin/sh
那么除了 /etc
中的几个文件(/etc/passwd
、/etc/group
以及它们的影子等价物)之外,您可能没有做任何更改。
如果你有:
RUN adduser example -D -h /example -s /bin/sh && \
chown -R example.example /lib
然后已更改的列表递归地包括 /lib
中的所有内容,这可能更大。事实上,在我的 alpine:edge
容器中, /lib
的内容看起来是 3.4MB:
/ # du -sh /lib
3.4M /lib
这正是您示例中图像大小变化的原因。
更新
使用您实际的 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/*
我得到:
$ docker build -t sotest .
[...]
Successfully built 058d9f41988a
$ docker inspect -f '{{.VirtualSize}}' 058d9f41988a
31783340
鉴于:
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/*
我得到:
$ docker build -t sotest .
[...]
Successfully built 696b481c5790
$ docker inspect -f '{{.VirtualSize}}' 696b481c5790
31789262
即两张图片大小差不多( 差异约为 5 Kb)。
如果 npm install
命令能够 运行 成功,我当然希望生成的图像更大(因为那样会安装额外的文件)。
现在您可以使用 ImageLayers.io 直观地检查您的图像及其图层,以帮助了解额外尺寸的原因。
另外, docker 历史显示了类似的东西。
不幸的是,这是一个已知问题:https://github.com/docker/docker/issues/5505 and https://github.com/docker/docker/issues/6119#issuecomment-70606158
您可以通过将 docker 存储驱动程序从 aufs 更改为 devicemapper 来解决此问题,如 https://github.com/docker/docker/issues/6119#issuecomment-268870519
中所述从 Docker 17.09 开始,可以在 Docker 文件中的 ADD/COPY 操作上使用 --chown
标志来更改 ADD/COPY 步骤本身的所有者而不是使用 chown 的单独 运行 操作,它会增加图像的大小,正如您所注意到的。最好将此作为默认模式,即复制文件的用户权限应用于复制的文件。但是,Docker 团队不想破坏向后兼容性,因此引入了一个新标志。
COPY --chown=<user>:<group> <hostPath> <containerPath>
其他备选方案是:
在构建映像之前更改暂存文件夹中的权限。
运行 通过 bootstrap 脚本更改所有权的容器。
压扁图层!