Edit 2018-09-26: Lots of edits to tidy up my mistakes and include all the dependencies. Much of my previous poking around is irrelevant, now that I've included all the dependencies and have numbers which add up sensibly.
I built an image from the provided repository in order to see the complete list of packages installed, including dependencies. My build did not complete, but it got far enough to produce an image (5ed25a4a3cf1
) which shows where the space is. Part way through the build, at the end of the RUN apk add ...
, it said this:
OK: 150 MiB in 102 packages
Looking at the image, we see that the packages are 145MB according to docker history
(image layer 8138a6c99655
- you probably need to scroll right to see the size column):
user@host:~/docker-craft-nginx$ sudo docker history 5ed25a4a3cf1
IMAGE CREATED CREATED BY SIZE COMMENT
5ed25a4a3cf1 About a minute ago /bin/sh -c #(nop) COPY dir:e9a848580d7409c11… 0B
79bba3526427 About a minute ago /bin/sh -c #(nop) COPY dir:41ddb696977d39ee6… 7.38kB
f4d1e79f00b4 About a minute ago /bin/sh -c #(nop) COPY dir:e9a848580d7409c11… 21B
ab8ad35f5a93 About a minute ago /bin/sh -c #(nop) COPY dir:4ff26c2555a73b795… 1.18kB
29a6368b96c5 About a minute ago /bin/sh -c #(nop) COPY dir:cb92d968d83d14948… 3.43kB
ea429fb6f1fa About a minute ago /bin/sh -c #(nop) COPY file:b1cc7638b7536f51… 139B
f0e1dbcec6c5 About a minute ago /bin/sh -c #(nop) COPY file:e0f1165c2cf43ac3… 1.07kB
8138a6c99655 About a minute ago /bin/sh -c apk add --no-cache bash n… 145MB
b743c478b647 2 minutes ago /bin/sh -c #(nop) LABEL description=Minimal… 0B
f3dab9765884 2 minutes ago /bin/sh -c #(nop) LABEL maintainer=Eivind M… 0B
196d12cf6ab1 11 days ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 11 days ago /bin/sh -c #(nop) ADD file:25c10b1d1b41d46a1… 4.41MB
Given the complete list of packages to install (they're shown during the image build), we can get their individual sizes using apk info -s NAME_OF_PACKAGE
(I've sorted them in order by decreasing size, and am only showing the first 20)
user@host:~$ sudo docker run -it alpine sh -c "apk update; apk info -s ncurses-terminfo-base ncurses-terminfo ncurses-libs readline bash libxau libbsd libxdmcp libxcb libx11 libxext libbz2 expat libpng freetype fontconfig libgcc libgomp lcms2 libltdl libxml2 imagemagick-libs libxrender pixman cairo libffi libintl libuuid libblkid libmount pcre glib dbus-libs avahi-libs gmp nettle p11-kit libtasn1 libunistring gnutls libstdc++ cups-libs jbig2dec libjpeg-turbo tiff ghostscript libxft graphite2 harfbuzz pango libcroco shared-mime-info gdk-pixbuf librsvg libwebp imagemagick nginx php7-common libedit php7 php7-ctype ca-certificates nghttp2-libs libssh2 libcurl php7-curl php7-dom php7-fileinfo php7-fpm libice libsm libxt libxpm php7-gd php7-iconv php7-imagick icu-libs php7-intl php7-json php7-mbstring php7-opcache php7-openssl php7-pdo php7-mysqlnd php7-pdo_mysql php7-phar php7-session libzip php7-zip" | awk '/^[0-9]/{gsub(/[^0-9]+$/,"",$1); print $1,prev,"\r"; next}{prev=$1}' | sort -gr | head -n 20
50036736 ghostscript-9.24-r0
31248384 icu-libs-60.2-r2
7245824 ncurses-terminfo-6.1_p20180818-r1
5070848 php7-fileinfo-7.2.10-r0
4849664 php7-fpm-7.2.10-r0
4775936 php7-7.2.10-r0
4489216 imagemagick-7.0.7.32-r0
3440640 imagemagick-libs-7.0.7.32-r0
3379200 libx11-1.6.5-r1
3010560 glib-2.56.1-r0
2338816 shared-mime-info-1.9-r0
2203648 harfbuzz-1.7.6-r1
1638400 php7-mbstring-7.2.10-r0
1470464 libunistring-0.9.7-r0
1384448 libstdc++-6.4.0-r8
1282048 gnutls-3.6.2-r0
1236992 p11-kit-0.23.10-r0
1224704 libxml2-2.9.8-r0
1187840 libcroco-0.6.12-r1
1175552 nginx-1.14.0-r1
Or a grand total size of all the packages put together:
user@host:~$ sudo docker run -it alpine sh -c "apk update; apk info -s ncurses-terminfo-base ncurses-terminfo ncurses-libs readline bash libxau libbsd libxdmcp libxcb libx11 libxext libbz2 expat libpng freetype fontconfig libgcc libgomp lcms2 libltdl libxml2 imagemagick-libs libxrender pixman cairo libffi libintl libuuid libblkid libmount pcre glib dbus-libs avahi-libs gmp nettle p11-kit libtasn1 libunistring gnutls libstdc++ cups-libs jbig2dec libjpeg-turbo tiff ghostscript libxft graphite2 harfbuzz pango libcroco shared-mime-info gdk-pixbuf librsvg libwebp imagemagick nginx php7-common libedit php7 php7-ctype ca-certificates nghttp2-libs libssh2 libcurl php7-curl php7-dom php7-fileinfo php7-fpm libice libsm libxt libxpm php7-gd php7-iconv php7-imagick icu-libs php7-intl php7-json php7-mbstring php7-opcache php7-openssl php7-pdo php7-mysqlnd php7-pdo_mysql php7-phar php7-session libzip php7-zip" | awk '/^[0-9]+/ {s+=$1} END {printf "%.0f\n", s}'
152952832
At this point, it looks like your problem is a "your stuff is too big" problem, rather than a docker problem. You may or may not have known that part before, but I've learned some stuff about digging in docker, so it's been fun :-)
Edit 2018-09-25: This is now not so useful, after correcting my earlier errors, but perhaps still has some relevant information: It occurs to me that even though my build of the full image failed, I don't care why - we're only interested in poking around in the big layer where the apks are installed. So, I made a fairly minimal dockerfile:
FROM alpine:3.8
# install nginx, php, and php extensions for Craft
RUN apk add --no-cache \
bash \
nginx \
php7 \
php7-fpm \
php7-opcache \
php7-phar \
php7-zlib \
php7-ctype \
php7-session \
php7-fileinfo \
# Required php extensions for Craft
php7-pdo \
php7-pdo_mysql \
php7-gd \
php7-openssl \
php7-mbstring \
php7-json \
php7-curl \
php7-zip \
# Optional extensions for Craft
php7-iconv \
php7-intl \
php7-dom \
# Extra Optional extensions for Craft
imagemagick \
php7-imagick
CMD sh
Built it: sudo docker build .
and got an image Successfully built e344a23763c9
. Running a container from this image with sudo docker run -it e344a23763c9
I got a shell. Installed ncdu
(which I could have installed via the dockerfile) with apk add --no-cache ncdu
then ran ncdu /
- now I can easily see where the big directories are, starting at the root (Note: I have trimmed small files & dirs from the output):
146.0 MiB [##########] /usr
3.6 MiB [ ] /lib
2.0 MiB [ ] /etc
1.4 MiB [ ] /bin
Navigating to /usr
we find:
84.4 MiB [##########] /lib
35.6 MiB [#### ] /share
20.5 MiB [## ] /bin
5.5 MiB [ ] /sbin
In /usr/lib
:
25.7 MiB [##########] libicudata.so.60.2
15.0 MiB [##### ] libgs.so.9.24
9.0 MiB [### ] /php7
3.9 MiB [# ] /ImageMagick-7.0.7
2.3 MiB [ ] libicui18n.so.60.2
2.2 MiB [ ] libMagickCore-7.Q16HDRI.so.6.0.0
1.5 MiB [ ] libicuuc.so.60.2
1.4 MiB [ ] libgio-2.0.so.0.5600.1
1.4 MiB [ ] libunistring.so.2.0.0
1.3 MiB [ ] libstdc++.so.6.0.22
1.2 MiB [ ] libgnutls.so.30.20.2
1.2 MiB [ ] libxml2.so.2.9.8
1.1 MiB [ ] libX11.so.6.3.0
1.1 MiB [ ] libMagickWand-7.Q16HDRI.so.6.0.0
1.1 MiB [ ] libp11-kit.so.0.3.0
In /usr/share
:
17.7 MiB [##########] /ghostscript
6.9 MiB [### ] /terminfo
5.6 MiB [### ] /mime
2.3 MiB [# ] /gtk-doc
2.1 MiB [# ] /X11
In /usr/bin
:
14.8 MiB [##########] gs
4.5 MiB [### ] php7
It looks to me like imagemagick
is the single biggest contributor (along with its dependency ghostscript
). Running a trial build without imagemagick
& php7-imagick
yields an image layer size of 65.8MB (as reported by docker history
).
Removing php7-intl
gets the layer down to 32.7MB (mostly by removing libicudata.so.60.2
which is part of "International Components for Unicode")
If you want a smaller container than your original, I think you you either need to do away with image processing and internationalisation, or find smaller ways to achieve them - they're far and away the largest possibly-trimmable components (depending on what you want to achieve).
You can get a tiny reduction in size/layers by combining your chmod
calls:
RUN chmod 777 -R \
/www/config \
/www/vendor \
/www/storage \
/www/web/cpresources \
&& chmod 777 \
/www/.env \
/www/composer.json \
/www/composer.lock
Edit 2018-09-29: I notice that the terminfo database in the image is [probably] excessive - almost 7MB according to the alpine package database entry for ncurses-terminfo. It has terminfos for virtually every possible term, which seems like overkill for a docker container (depending on what you are doing).
I can't see an easy way to not install that package (other things require it to be installed and I couldn't find a sensible way to force apk
to not honor the dependency), but you could get the RUN apk add ...
line to delete the unused terminfos before the layer is committed - delete most of these files.