减小 docker 镜像的大小

eiv*_*dml 5 php nginx docker alpine-linux craftcms

我正在尝试使用 Docker 将 Craft CMS 部署到zeit/now。它在本地工作,但 zeit 的图像大小限制为100MB. 我的容器目前是176MB.

\n\n

它是一个 Docker 镜像alpine,使用 Craft 所需的nginxphp模块,并使用多阶段构建来构建 Composer 组件,以减少构建工件的大小。

\n\n

这是Dockerfile

\n\n
FROM zeit/wait-for:0.2 as wait\n\n# Build dependencies\nFROM composer:latest as vendor\n\nCOPY composer.json composer.json\nCOPY composer.lock composer.lock\n\nRUN composer install --ignore-platform-reqs --no-interaction --no-plugins --no-scripts --prefer-dist --no-dev\n\nFROM alpine:3.8\n\nLABEL maintainer="Eivind Mikael Lindbr\xc3\xa5ten <eivindml@icloud.com>"\nLABEL description="Minimal Craft CMS Container using nginx."\n\n# install nginx, php, and php extensions for Craft\nRUN apk add --no-cache \\\n    bash \\\n    nginx \\\n    php7 \\\n    php7-fpm \\\n    php7-opcache \\\n    php7-phar \\\n    php7-zlib \\\n    php7-ctype \\\n    php7-session \\\n    php7-fileinfo \\\n# Required php extensions for Craft\n    php7-pdo \\\n    php7-pdo_mysql \\\n    php7-gd \\\n    php7-openssl \\\n    php7-mbstring \\\n    php7-json \\\n    php7-curl \\\n    php7-zip \\\n# Optional extensions for Craft\n    php7-iconv \\\n    php7-intl \\\n    php7-dom\n\nCOPY nginx.conf /etc/nginx/nginx.conf\nCOPY www.conf /etc/php7/php-fpm.d/\n\n# Copy over Craft files\nCOPY config/ /www/config\nCOPY modules/ /www/modules\nCOPY storage/ /www/storage\nCOPY templates/ /www/templates\nCOPY storage/ /www/storage\nCOPY web/ /www/web\nCOPY .env /www/.env\nCOPY composer.json /www/composer.json\nCOPY composer.lock /www/composer.lock\n\n# Copy over vendor files\nCOPY --from=vendor /app/vendor /www/vendor\n\n# Set permissions\nRUN chmod 777 -R /www/config\nRUN chmod 777 -R /www/vendor\nRUN chmod 777 -R /www/storage\nRUN chmod 777 -R /www/web/cpresources\nRUN chmod 777 /www/.env\nRUN chmod 777 /www/composer.json\nRUN chmod 777 /www/composer.lock\n\n# Expose default port\nEXPOSE 80\n\nSHELL ["/bin/bash", "-c"]\nCOPY --from=wait /bin/wait-for /bin/wait-for\n\nCMD php-fpm7 -F & (wait-for /tmp/php7-fpm.sock && nginx) & wait -n\n
Run Code Online (Sandbox Code Playgroud)\n\n

有什么想法可以进一步减小这个尺寸吗?

\n

Kar*_*lMW 5

编辑 2018-09-26:大量编辑来整理我的错误并包含所有依赖项。我之前的大部分探索都是无关紧要的,现在我已经包含了所有依赖项并且有了合理累加的数字。

\n\n
\n\n

我从提供的存储库构建了一个映像,以便查看已安装的包的完整列表,包括依赖项。我的构建尚未完成,但已经足够生成一个图像 ( 5ed25a4a3cf1),该图像显示空间所在位置。在构建的过程中,在 的末尾RUN apk add ...,它这样说:

\n\n
OK: 150 MiB in 102 packages\n
Run Code Online (Sandbox Code Playgroud)\n\n

查看图像,我们发现包大小为 145MB docker history(图像层8138a6c99655- 您可能需要向右滚动才能看到大小列):

\n\n
user@host:~/docker-craft-nginx$ sudo docker history 5ed25a4a3cf1\nIMAGE               CREATED              CREATED BY                                      SIZE                COMMENT\n5ed25a4a3cf1        About a minute ago   /bin/sh -c #(nop) COPY dir:e9a848580d7409c11\xe2\x80\xa6   0B\n79bba3526427        About a minute ago   /bin/sh -c #(nop) COPY dir:41ddb696977d39ee6\xe2\x80\xa6   7.38kB\nf4d1e79f00b4        About a minute ago   /bin/sh -c #(nop) COPY dir:e9a848580d7409c11\xe2\x80\xa6   21B\nab8ad35f5a93        About a minute ago   /bin/sh -c #(nop) COPY dir:4ff26c2555a73b795\xe2\x80\xa6   1.18kB\n29a6368b96c5        About a minute ago   /bin/sh -c #(nop) COPY dir:cb92d968d83d14948\xe2\x80\xa6   3.43kB\nea429fb6f1fa        About a minute ago   /bin/sh -c #(nop) COPY file:b1cc7638b7536f51\xe2\x80\xa6   139B\nf0e1dbcec6c5        About a minute ago   /bin/sh -c #(nop) COPY file:e0f1165c2cf43ac3\xe2\x80\xa6   1.07kB\n8138a6c99655        About a minute ago   /bin/sh -c apk add --no-cache     bash     n\xe2\x80\xa6   145MB\nb743c478b647        2 minutes ago        /bin/sh -c #(nop)  LABEL description=Minimal\xe2\x80\xa6   0B\nf3dab9765884        2 minutes ago        /bin/sh -c #(nop)  LABEL maintainer=Eivind M\xe2\x80\xa6   0B\n196d12cf6ab1        11 days ago          /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B\n<missing>           11 days ago          /bin/sh -c #(nop) ADD file:25c10b1d1b41d46a1\xe2\x80\xa6   4.41MB\n
Run Code Online (Sandbox Code Playgroud)\n\n

给定要安装的软件包的完整列表(它们在映像构建过程中显示),我们可以使用以下命令获取它们各自的大小apk info -s NAME_OF_PACKAGE

\n\n

(我已经按照大小递减的顺序对它们进行了排序,并且只显示前 20 个)

\n\n
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\n50036736 ghostscript-9.24-r0\n31248384 icu-libs-60.2-r2\n7245824 ncurses-terminfo-6.1_p20180818-r1\n5070848 php7-fileinfo-7.2.10-r0\n4849664 php7-fpm-7.2.10-r0\n4775936 php7-7.2.10-r0\n4489216 imagemagick-7.0.7.32-r0\n3440640 imagemagick-libs-7.0.7.32-r0\n3379200 libx11-1.6.5-r1\n3010560 glib-2.56.1-r0\n2338816 shared-mime-info-1.9-r0\n2203648 harfbuzz-1.7.6-r1\n1638400 php7-mbstring-7.2.10-r0\n1470464 libunistring-0.9.7-r0\n1384448 libstdc++-6.4.0-r8\n1282048 gnutls-3.6.2-r0\n1236992 p11-kit-0.23.10-r0\n1224704 libxml2-2.9.8-r0\n1187840 libcroco-0.6.12-r1\n1175552 nginx-1.14.0-r1\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者所有包放在一起的总大小:

\n\n
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}\'\n152952832\n
Run Code Online (Sandbox Code Playgroud)\n\n

此时,看起来您的问题是“您的东西太大”问题,而不是 docker 问题。你之前可能知道也可能不知道这一部分,但我已经学到了一些关于在 docker 中挖掘的东西,所以这很有趣:-)

\n\n
\n\n

编辑2018-09-25:在纠正了我之前的错误之后,这现在不太有用,但也许仍然有一些相关信息:我发现,即使我的完整图像构建失败了,我也不关心为什么- 我们只对在安装 apk 的大层中进行探索感兴趣。所以,我制作了一个相当小的 dockerfile:

\n\n
FROM alpine:3.8\n\n# install nginx, php, and php extensions for Craft\nRUN apk add --no-cache \\\n    bash \\\n    nginx \\\n    php7 \\\n    php7-fpm \\\n    php7-opcache \\\n    php7-phar \\\n    php7-zlib \\\n    php7-ctype \\\n    php7-session \\\n    php7-fileinfo \\\n# Required php extensions for Craft\n    php7-pdo \\\n    php7-pdo_mysql \\\n    php7-gd \\\n    php7-openssl \\\n    php7-mbstring \\\n    php7-json \\\n    php7-curl \\\n    php7-zip \\\n# Optional extensions for Craft\n    php7-iconv \\\n    php7-intl \\\n    php7-dom \\\n# Extra Optional extensions for Craft\n    imagemagick \\\n    php7-imagick\n\nCMD sh\n
Run Code Online (Sandbox Code Playgroud)\n\n

构建它:sudo docker build .并获得图像Successfully built e344a23763c9。使用这个镜像运行一个容器,sudo docker run -it e344a23763c9我得到了一个 shell。安装ncdu(我可以通过 dockerfile 安装)然后apk add --no-cache ncdu运行ncdu /​​- 现在我可以轻松地看到大目录在哪里,从根开始(注意:我已经从输出中修剪了小文件和目录):

\n\n
  146.0 MiB [##########] /usr                                                                                                                                  \n    3.6 MiB [          ] /lib\n    2.0 MiB [          ] /etc\n    1.4 MiB [          ] /bin\n
Run Code Online (Sandbox Code Playgroud)\n\n

导航到/usr我们发现:

\n\n
   84.4 MiB [##########] /lib\n   35.6 MiB [####      ] /share\n   20.5 MiB [##        ] /bin\n    5.5 MiB [          ] /sbin\n
Run Code Online (Sandbox Code Playgroud)\n\n

/usr/lib

\n\n
   25.7 MiB [##########]  libicudata.so.60.2\n   15.0 MiB [#####     ]  libgs.so.9.24\n    9.0 MiB [###       ] /php7\n    3.9 MiB [#         ] /ImageMagick-7.0.7\n    2.3 MiB [          ]  libicui18n.so.60.2\n    2.2 MiB [          ]  libMagickCore-7.Q16HDRI.so.6.0.0\n    1.5 MiB [          ]  libicuuc.so.60.2\n    1.4 MiB [          ]  libgio-2.0.so.0.5600.1\n    1.4 MiB [          ]  libunistring.so.2.0.0\n    1.3 MiB [          ]  libstdc++.so.6.0.22\n    1.2 MiB [          ]  libgnutls.so.30.20.2\n    1.2 MiB [          ]  libxml2.so.2.9.8\n    1.1 MiB [          ]  libX11.so.6.3.0\n    1.1 MiB [          ]  libMagickWand-7.Q16HDRI.so.6.0.0\n    1.1 MiB [          ]  libp11-kit.so.0.3.0\n
Run Code Online (Sandbox Code Playgroud)\n\n

/usr/share

\n\n
   17.7 MiB [##########] /ghostscript\n    6.9 MiB [###       ] /terminfo\n    5.6 MiB [###       ] /mime\n    2.3 MiB [#         ] /gtk-doc\n    2.1 MiB [#         ] /X11\n
Run Code Online (Sandbox Code Playgroud)\n\n

/usr/bin

\n\n
   14.8 MiB [##########]  gs\n    4.5 MiB [###       ]  php7\n
Run Code Online (Sandbox Code Playgroud)\n\n

在我看来,它imagemagick是最大的贡献者(及其依赖性ghostscript)。imagemagick运行不带&的试用构建php7-imagick会产生 65.8MB 的图像层大小(如 所报告docker history)。

\n\n

删除后,php7-intl该层的大小会减少到 32.7MB(主要是删除libicudata.so.60.2“International Components for Unicode”的一部分)

\n\n

如果您想要一个比原始容器更小的容器,我认为您要么需要取消图像处理和国际化,要么找到更小的方法来实现它们 - 它们无疑是最大的可能可修剪的组件(取决于什么)你想要实现的目标)。

\n\n
\n\n

您可以通过组合调用来稍微减少尺寸/层数chmod

\n\n
RUN chmod 777 -R \\\n   /www/config \\\n   /www/vendor \\\n   /www/storage \\\n   /www/web/cpresources \\\n&& chmod 777 \\\n   /www/.env \\\n   /www/composer.json \\\n   /www/composer.lock\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

编辑 2018-09-29:我注意到图像中的 terminfo 数据库[可能]过多 - 根据ncurses-terminfo 的alpine 包数据库条目,几乎为 7MB 。它几乎为每个可能的术语提供了 terminfos,这对于 docker 容器来说似乎有点大材小用(取决于你在做什么)。

\n\n

我看不到一种不安装该软件包的简单方法(其他东西需要安装它,并且我找不到一种明智的方法来强制apk不遵守依赖关系),但是您可以获取RUN apk add ...删除该软件包的行在提交层之前未使用的 terminfos - 删除其中大部分文件

\n


Mur*_*nik -2

您当然可以做的一件事是apk在所有apk add调用完成后删除缓存:

RUN rm -rf /var/cache/apk
Run Code Online (Sandbox Code Playgroud)

  • 我正在为“apk”使用“--no-cache”标志。[从 Alpine Linux 3.3 开始,apk 存在一个新的 --no-cache 选项。它允许用户安装带有索引的软件包,该索引是动态更新和使用的,而不是本地缓存的。这避免了在完成安装包时使用 --update 和删除 /var/cache/apk/* 的需要。](https://github.com/gliderlabs/docker-alpine/blob/master/docs/usage.md) (5认同)