卸载 docker 内的应用程序?
Uninstall applications within docker?
我正在使用 docker 构建和 运行 一组服务。对于其中之一,我需要安装一些包以完成内部 (gulp.js) 构建过程,但它们在最终的 docker 图像中不是必需的。似乎我应该在构建 docker 图像时卸载它们,以保持图像更小。有这方面的标准做法吗?
相关:docker 图片的合理尺寸是多少?我意识到 "reasonable" 是主观的,但是 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}
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
如何修复
我看到了两种减小图片大小的可能性:
确保您的 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
目录。
"Squash" 图像层合二为一。 docker-squash
之类的工具可能对此有所帮助。请注意,压缩图像层会使(通常非常有效的)docker push
和 docker pull
操作效率降低。通常,这些操作仅传输本地(pull
ing 时)或远程(push
ing 时)尚未存在的图像的特定层。当您的图像仅包含一层时,docker push
和 pull
将始终传输整个图像。
我正在使用 docker 构建和 运行 一组服务。对于其中之一,我需要安装一些包以完成内部 (gulp.js) 构建过程,但它们在最终的 docker 图像中不是必需的。似乎我应该在构建 docker 图像时卸载它们,以保持图像更小。有这方面的标准做法吗?
相关:docker 图片的合理尺寸是多少?我意识到 "reasonable" 是主观的,但是 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}
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
如何修复
我看到了两种减小图片大小的可能性:
确保您的
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
目录。"Squash" 图像层合二为一。
docker-squash
之类的工具可能对此有所帮助。请注意,压缩图像层会使(通常非常有效的)docker push
和docker pull
操作效率降低。通常,这些操作仅传输本地(pull
ing 时)或远程(push
ing 时)尚未存在的图像的特定层。当您的图像仅包含一层时,docker push
和pull
将始终传输整个图像。