Уменьшить размер образа докера

Я пытаюсь развернуть Craft CMS в Zeit / в настоящее время используя Docker. Это работает локально, но Zeit имеет ограничение размера изображения 100MB, Мой контейнер в настоящее время 176MB,

Это изображение Docker, использующее alpine, nginx а также php модули, необходимые для Craft, и использование многоступенчатой ​​сборки для сборки компонентов Composer, чтобы уменьшить размер артефактов сборки.

Это Dockerfile:

FROM zeit/wait-for:0.2 as wait

# Build dependencies
FROM composer:latest as vendor

COPY composer.json composer.json
COPY composer.lock composer.lock

RUN composer install --ignore-platform-reqs --no-interaction --no-plugins --no-scripts --prefer-dist --no-dev

FROM alpine:3.8

LABEL maintainer="Eivind Mikael Lindbråten <eivindml@icloud.com>"LABEL description="Minimal Craft CMS Container using nginx."
# 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

COPY nginx.conf /etc/nginx/nginx.conf
COPY www.conf /etc/php7/php-fpm.d/

# Copy over Craft files
COPY config/ /www/config
COPY modules/ /www/modules
COPY storage/ /www/storage
COPY templates/ /www/templates
COPY storage/ /www/storage
COPY web/ /www/web
COPY .env /www/.env
COPY composer.json /www/composer.json
COPY composer.lock /www/composer.lock

# Copy over vendor files
COPY --from=vendor /app/vendor /www/vendor

# Set permissions
RUN chmod 777 -R /www/config
RUN chmod 777 -R /www/vendor
RUN chmod 777 -R /www/storage
RUN chmod 777 -R /www/web/cpresources
RUN chmod 777 /www/.env
RUN chmod 777 /www/composer.json
RUN chmod 777 /www/composer.lock

# Expose default port
EXPOSE 80

SHELL ["/bin/bash", "-c"]
COPY --from=wait /bin/wait-for /bin/wait-for

CMD php-fpm7 -F & (wait-for /tmp/php7-fpm.sock && nginx) & wait -n

Любые идеи, как я могу уменьшить этот размер дальше?

4

Решение

Изменить 2018-09-26: множество правок, чтобы привести в порядок мои ошибки и включить все зависимости. Большая часть моего предыдущего осмотра не имеет значения, теперь, когда я включил все зависимости и имею числа, которые складываются разумно.


Я создал образ из предоставленного репозитория, чтобы увидеть полный список установленных пакетов, включая зависимости. Моя сборка не была завершена, но она прошла достаточно далеко для создания изображения (5ed25a4a3cf1) который показывает, где находится пространство. Часть пути через сборку, в конце RUN apk add ...Сказал это:

OK: 150 MiB in 102 packages

Глядя на изображение, мы видим, что пакеты составляют 145 МБ в соответствии с docker history (слой изображения 8138a6c99655 — вам, вероятно, нужно прокрутить вправо, чтобы увидеть столбец размера):

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

Учитывая полный список пакетов для установки (они показаны во время сборки образа), мы можем получить их индивидуальные размеры, используя apk info -s NAME_OF_PACKAGE

(Я отсортировал их по порядку, уменьшив размер, и показываю только первые 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

Или общий размер всех пакетов вместе взятых:

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

На данный момент, похоже, что ваша проблема — проблема «у вас слишком большой материал», а не проблема докера. Вы могли или не могли знать эту часть раньше, но я узнал кое-что о копании в докере, так что это было весело 🙂


Изменить 2018-09-25: теперь это не так полезно после исправления моих предыдущих ошибок, но, возможно, все еще содержит некоторую соответствующую информацию: мне приходит в голову, что, хотя моя сборка полного изображения не удалась, мне все равно, почему — Мы заинтересованы только в том, чтобы ковыряться в большом слое, где установлены apks. Итак, я сделал довольно минимальный 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

Построил это: sudo docker build . и получил изображение Successfully built e344a23763c9, Запуск контейнера из этого изображения с sudo docker run -it e344a23763c9 Я получил снаряд Установлены ncdu (который я мог бы установить через dockerfile) с apk add --no-cache ncdu затем побежал ncdu / — теперь я могу легко видеть, где находятся большие каталоги, начиная с корня (Примечание: я обрезал маленькие файлы & dirs с выхода):

  146.0 MiB [##########] /usr
3.6 MiB [          ] /lib
2.0 MiB [          ] /etc
1.4 MiB [          ] /bin

Навигация к /usr мы нашли:

   84.4 MiB [##########] /lib
35.6 MiB [####      ] /share
20.5 MiB [##        ] /bin
5.5 MiB [          ] /sbin

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

В /usr/share:

   17.7 MiB [##########] /ghostscript
6.9 MiB [###       ] /terminfo
5.6 MiB [###       ] /mime
2.3 MiB [#         ] /gtk-doc
2.1 MiB [#         ] /X11

В /usr/bin:

   14.8 MiB [##########]  gs
4.5 MiB [###       ]  php7

Это выглядит как imagemagick является единственным крупнейшим вкладчиком (вместе с его зависимостью ghostscript). Запуск пробной сборки без imagemagick & php7-imagick дает размер слоя изображения 65,8 МБ (как сообщает docker history).

Удаление php7-intl получает слой до 32,7 МБ (в основном, удаляя libicudata.so.60.2 который является частью «Международные компоненты для Unicode»)

Если вы хотите контейнер меньшего размера, чем ваш оригинал, я думаю, что вам нужно либо покончить с обработкой изображений и интернационализацией, либо найти меньшие способы для их достижения — это самые большие компоненты, которые можно подрезать (в зависимости от того, что вы хочу добиться).


Вы можете получить небольшое уменьшение в размере / слоях, комбинируя chmod звонки:

RUN chmod 777 -R \
/www/config \
/www/vendor \
/www/storage \
/www/web/cpresources \
&& chmod 777 \
/www/.env \
/www/composer.json \
/www/composer.lock

Изменить 2018-09-29: я заметил, что база данных terminfo в изображении [вероятно] чрезмерна — почти 7 МБ в соответствии с записью базы данных пакета Alpine для Ncurses-TERMINFO. У него есть terminfos практически для каждого возможного термина, что кажется избыточным для контейнера докера (в зависимости от того, что вы делаете).

Я не вижу простого способа не установить этот пакет (другие вещи требуют его установки, и я не смог найти разумный способ заставить его apk не уважать зависимость), но вы могли бы получить RUN apk add ... строка для удаления неиспользованных terminfos перед фиксацией слоя — удалить большинство из них файлы.

4

Другие решения

Одна вещь, которую вы, безусловно, можете сделать, это удалить apk кеш в конце концов apk add звонки сделаны:

RUN rm -rf /var/cache/apk
-1