减小Docker镜像的大小

5
我正在尝试使用Docker将Craft CMS部署到 zeit/now。它在本地工作,但是zeit有一个图像大小限制为100MB。我的容器目前为176MB
这是一个Docker镜像,使用alpinenginx和Craft所需的php模块,并使用多阶段构建来构建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

有什么想法可以进一步减小这个大小吗?
2个回答

5

编辑于2018年9月26日:进行了大量编辑来整理我的错误并包含所有依赖项。现在,我已经包含了所有依赖项,并且有合理的数字,因此我以前的探索大部分都是无关紧要的。


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

OK: 150 MiB in 102 packages

从图片中可以看出,根据 docker history 命令查询的结果(镜像层 8138a6c99655 - 你可能需要向右滚动来查看大小列),这些软件包的大小为145MB:

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

目前看来,你的问题是一个“文件过大”的问题,而不是一个Docker问题。 你可能之前已经知道了这部分内容,但我在挖掘Docker方面学到了一些东西,感觉很有趣 :-)

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。使用该镜像启动容器并进入shell sudo docker run -it e344a23763c9。安装ncdu工具(也可以通过dockerfile安装):apk add --no-cache ncdu,然后运行ncdu /,现在可以轻松查看文件夹占用空间,从根目录开始(注意:输出已省略小文件和目录)。

  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

我认为,除了其依赖项ghostscript外,imagemagick是最大的贡献者。如果没有imagemagickphp7-imagick,则运行试验性构建将产生65.8MB的图像层大小(由docker history报告)。
删除php7-intl可将图层大小降至32.7MB(主要是通过删除“Unicode国际组件”中的libicudata.so.60.2实现的)。
如果您想要比原来更小的容器,则需要放弃图像处理和国际化,或者找到更小的方法来实现它们-它们是最大的可裁剪组件(取决于您想要实现什么)。
通过合并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年9月29日:我注意到镜像中的terminfo数据库[可能]过于庞大 - 根据ncurses-terminfo的Alpine软件包数据库条目,它几乎占用了7MB。 它具有几乎每个可能术语的terminfos,这似乎对于Docker容器来说有些过度 (取决于您要做什么)。

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


1
哇。这真的很有帮助和趣味。谢谢。我猜如果问题是“php太大了”,那么就没有什么可以做的了?我试着不安装可选的php包,但大小根本没变。 - eivindml
我得到了一个关于这个网站的提示:https://microbadger.com/images/eivindml/docker-craft-nginx 它可以分解大小。但是在这里它显示为87mb。 - eivindml
1
Microbadger报告的87MB很有趣。今天我没有更多的想法,但是很想再调查一下。在今天修剪imagemagick的实验之后,我注意到我的软件包和大小列表(我的答案中的第一个大代码块)仍然不正确 - 当我包括所有内容时,数字总共约为150MB。我明天会更新我的帖子。 - KarlMW
1
我已经更新并整理了我的答案-进行了许多编辑,但我认为它们都很有意义,并且我学到了未来可以再次使用的东西。 - KarlMW
哇。这非常有用。:) 现在唯一的问题是为什么 https://microbadger.com/images/eivindml/docker-craft-nginx 报告的是87mb。看起来计算大小的方式有不同?他们称其为“下载大小”,所以可能这是另一件事情,而不是ssh进入每个文件夹时的大小。也许这就是Zeit/now正在查看的值,这就是为什么即使他们有100mb的限制,它也被部署的原因。 - eivindml
显示剩余3条评论


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接