在docker中卸载应用程序?

时间:2016-12-09 20:12:58

标签: ubuntu docker apt-get

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

相关:码头图像的合理大小是多少?我觉得“合理”是主观的,但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 -e s/graceful-fs/fs-extra/ -e s/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}

1 个答案:

答案 0 :(得分:2)

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

在构建步骤中删除包不会减少整体图像大小,因为删除的文件仍将存在于父图层中(尽管从此图像创建容器时文件将被标记为已删除但不存在)。

实施例

考虑一个简短的例子:

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

此示例Dockerfile在第一个RUN语句中创建一个包含100 MiB文件的图像,并在第二个RUN语句中将其删除。现在使用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

如何修复

我看到两种缩小图像尺寸的可能性:

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

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

    此语句仅在结果图像中创建单个文件系统层,而不包含node_modules目录。

  2. 将图像层“压缩”为一个。像docker-squash这样的工具可能对此有所帮助。请注意,压缩图像层会使(通常效率极高)docker pushdocker pull操作效率降低。通常,这些操作仅传输图像的特定层,这些层在本地(pull)或远程(当push)侧时尚未存在。如果您的图片只包含一个图层,docker pushpull将始终传输整个图片。