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