在docker中卸载应用程序?

我正在使用docker来构build和运行一组服务。 对于其中之一,我需要安装一些软件包以完成内部(gulp.js)构build过程,但是在最终的泊坞窗镜像中它们不是必需的。 似乎我应该卸载它们,同时build立docker图像,以保持图像更小。 这是否有一个标准的做法?

相关:docker图像的合理尺寸是多less? 我意识到“合理”是主观的,但1.4 GB的声音是否狂野?

这是我的Dockerfile,因为它现在存在:

FROM python:3.5.1-onbuild ARG mode=dev ENV MODE $mode RUN apt-get update && apt-get install -y \ build-essential \ curl \ && rm -rf /var/lib/apt/lists/* RUN curl -sL https://deb.nodesource.com/setup_6.x | bash RUN apt-get install -y nodejs RUN cd $(npm root -g)/npm \ && npm install fs-extra \ && sed -i -es/graceful-fs/fs-extra/ -es/fs\.rename/fs.move/ ./lib/utils/rename.js WORKDIR /usr/src/app/app RUN npm install RUN npm install --global gulp-cli RUN npm rebuild node-sass RUN gulp RUN rm -rf node_modules WORKDIR /usr/src/app EXPOSE 8080 RUN python3 setup.py install CMD python3 manage.py ${MODE} 

Docker镜像使用分层文件系统。 Dockerfile每个语句都会导致将新图层添加到生成的图像中。 您可以使用docker history命令检查这些图层。

在构build步骤中删除软件包不会减less整个映像的大小,因为删除的文件仍然会出现在父层中(尽pipe当您从该映像创build容器时文件将被标记为已删除且不存在)。

考虑一个简短的例子:

 FROM debian:8 RUN dd if=/dev/zero of=/tmp/test bs=1024 count=100K RUN rm /tmp/test 

本示例Dockerfile在第一个RUN语句中创build一个包含100 MiB文件的映像,并在第二个RUN语句中将其删除。 现在使用docker history <image-id>检查创build的图像docker history <image-id>

 IMAGE CREATED CREATED BY SIZE COMMENT 02b8c1077ac1 8 seconds ago /bin/sh -c rm /tmp/test 0 B 64a98e72b7ca 8 seconds ago /bin/sh -c dd if=/dev/zero of=/tmp/test bs=10 104.9 MB 737e719de6a4 4 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B 1f2a121fc3e4 4 weeks ago /bin/sh -c #(nop) ADD file:41ea5187c50116884c 123 MB 

正如你所看到的,100MiB层还在那里。 生成的图像总体大小约为200MB:

 REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE <none> <none> 02b8c1077ac1 8 minutes ago 227.9 MB 

怎么修

我看到两种可能性来减less图像大小:

  1. 确保您的npm install命令和后续的rm -rf node_modules在相同的构build步骤中运行:

     RUN npm install && \ npm install --global gulp-cli && \ npm rebuild node-sass && \ gulp && \ rm -rf node_modules 

    这个语句只会在生成的映像中创build一个文件系统层,而不包含node_modules目录。

  2. 将图像层压缩成一个。 像docker-squash这样的工具可能会有所帮助。 请注意,压缩图像层使得(通常是非常高效的) docker pushdocker pull操作效率较低。 通常情况下,这些操作只传输图像的特定图层,这些图层在本地( pull入时)或远程(当push )时不存在。 当您的图像只包含一层时, docker push将始终传送整个图像。