Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does chown increase size of docker image?

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

The following Dockerfile creates an image of size 5.3MB:

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

This example however creates an image of size 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..

like image 382
Fractalf Avatar asked May 06 '15 19:05

Fractalf


Video Answer


1 Answers

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.

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).

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:

/ # 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:

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).

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).

like image 158
larsks Avatar answered Sep 28 '22 04:09

larsks