MySQL, Oracle, Linux, 软件架构及大数据技术知识分享平台

网站首页 > 精选文章 / 正文

Docker[容器]镜像瘦身180倍后还能正常运行不?

2025-01-16 19:42 huorong 精选文章 4 ℃ 0 评论


Docker容器的方便都有体会吧,随着各种AI/ML/LLM的普及,大模型时代已经到来,试想一下,容器内安装个PyTorch包就上G大小,再加上CUDA,最终的镜像5G已经打不住了,这都还不算模型本身,是不是恐怖如斯!

不仅仅是大模型的容器镜像,我们常用的APP进出环境镜像,比如Tomcat,Python,Nodejs等也都是轻松几百M大小,即使使用私有镜像仓库,每次更新镜像也会给带宽和流量产生一定的压力,所以,对镜像进行瘦身可以考虑到日程上了。

也都希望我们都使用着几十M的小Image,更新,部署时轻轻松松迅速拉起来!要知道这种精简后的Docker镜像可以大大提高应用部署效率和减少资源的占用!

之前我也尝试过对容器镜像的优化和缩减:

比如减少层级,使用更轻量级的基础镜像(Alpine及各种slim镜像),清理不必要的安装包删除临时文件和日志。如Dockerfile中:

FROM alpine:latest
...
RUN hash -r \
    && apt-get clean \
    && rm -rf \
        /var/lib/apt/lists/* \
        /tmp/* \
        /var/tmp/* \
        /usr/share/man \
        /usr/share/doc \
        /usr/share/doc-base

以上操作确实可以减少一些镜像的大小,但是缩减比例还是有限,今天就给大家介绍一款在容器镜像瘦身这块的超级“狠角色”:slim
https://github.com/slimtoolkit/slim/
),

Slim 不会更改容器映像中的任何内容,也不需要修改Dockerfile,瘦身后的容器更小、也更安全(减少CVE),官方称普遍可以缩小镜像30倍左右。

哈哈,既然是这么牛的工具,赶紧拿来折腾折腾。

我这里测试使用了Slim的两种安装方式:容器和二级制文件

容器方式安装

$ cat docker-compose.yml
services:
  dslim:
    # image: dslim/slim:latest
    image: dslim/docker-slim:latest
    container_name: dslim
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

二进制可执行文件方式安装

wget https://github.com/slimtoolkit/slim\
  /releases/download/1.40.11/dist_linux.tar.gz
tar zxvf dist_linux.tar.gz
解压后这样:
$ ls -tlr
总计 54864
-rwxr-xr-x 1 fisher fisher  6012928  3月  3  2024 slim-sensor
-rwxr-xr-x 1 fisher fisher 50143232  3月  3  2024 slim
lrwxrwxrwx 1 fisher fisher        4  3月  3  2024 docker-slim -> slim

命令行操作

>>> help
NAME:
   slim - inspect, optimize and debug your containers!

USAGE:
   slim [global options] command [command options] [arguments...]

VERSION:
   linux/amd64|Transformer|1.40.11|1b271555882eacdfb4e6598d6d0552e9b9b1449b|2024-02-02_01:36:22PM
COMMANDS:
   xray, x              Shows what's inside of your container image and reverse engineers its Dockerfile
   lint, l              Analyzes container instructions in Dockerfiles
   build, b             Analyzes, profiles and optimizes your container image auto-generating Seccomp and AppArmor security profiles
   merge, m             Merge two container images (optimized to merge minified images)
   images, i            Get information about container images
   registry, r          Execute registry operations
   vulnerability, vuln  Execute vulnerability related tools and operations
   profile, p           Collects fat image information and generates a fat container report
   version, v           Shows slim and docker version information
   appbom, a            Show application BOM
   help, h              Show help info
   update, u            Updates slim
   install, in          Installs slim
   run, r               Run one or more containers
   debug, dbg           Debug the target container from a debug (side-car) container
   internal.metadata:
     docker-cli-plugin-metadata  Plugin metadata for the docker cli

OK,接下来的例子会对我们常见的三种镜像进行瘦身,分别是Nginx,Python3,Tomcat,然后我们来看看最后的瘦身效果究竟如何!

Nginx镜像瘦身

首先从hub官网下载latest镜像,大小为192M

$ docker ps | grep nginx
nginx latest 60c8a892f36f 6 weeks ago 192MB

使用compose测试下Nginx原始镜像是否工作正常

$ cat docker-compose.yml
services:
  nginx-slim-test:
    image: nginx:latest
    #image: nginx.slim:latest
    container_name: nginx-slim-test
    restart: always
    tty: true
    stdin_open: true
    ports:
      - "8005:80"

$ docker compose up -d 

然后测试http访问

curl localhost:8005

可以看到运行正常。

现在开始对镜像进行瘦身,执行命令:

./slim build nginx:latest

查看下当前镜像情况,镜像后面添加了一个.slim,然后镜像从192M缩减到了13.3M:

$ docker images | grep nginx
nginx.slim latest bd36a 2 hours ago  13.3MB
nginx      latest 60c8a 6 weeks ago  192MB

瘦身之后的Nginx镜像能否正常运行呢?使用docker-compose启动试试看

可以看到Nginx运行正常

瘦身后只有13.3M的镜像里面还能有点啥呢?使用之前的bash想进去看看,然后发现很多系统基础的命令都没有,比如ls,cat,df,top等,这Slim真是“够狠”!

Python镜像瘦身

从hub上下载最新的python:3.13镜像

$ docker pull python:3.13.0

原始的python3.13镜像大小居然1.02G!

$ docker images | grep python
python 3.13.0 c41ea8273365 4 weeks ago 1.02GB

不能只是简单测试python命令吧,不太科学,这回我们简单模式一个使用python3启动web服务的例子,以python:3.13.0为基础镜像,使用flask启动一个webserver。

$ cat requirements.txt
wheel==0.45.0
Jinja2==3.1.2
requests==2.32.3
simplejson==3.19.3
Flask==3.1.0

python启动文件

$ cat app.py
from flask import Flask, render_template_string

app = Flask(__name__)

@app.route('/')
def hello_world():
    return render_template_string('''
        <!DOCTYPE html>
        <html>
            <head>
                <title>Hello, World!</title>
            </head>
            <body>
                <h1>Hello, World!</h1>
            </body>
        </html>
    ''')

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000)

再弄一个简单的Dockerfile,把依赖和app.py打进去,让容器自动启动,并监听8000端口

FROM python:3.13.0
MAINTAINER fisher <fisher@mymailbox.com>
WORKDIR /root/

COPY requirements.txt /tmp/requirements.txt
COPY app.py /root/app.py
RUN pip3 install -r /tmp/requirements.txt \
    -i https://pypi.tuna.tsinghua.edu.cn/simple
EXPOSE 8000
CMD ["python3", "app.py"]

RUN hash -r \
    && apt-get clean \
    && rm -rf \
        /var/lib/apt/lists/* \
        /tmp/* \
        /var/tmp/* \
        /usr/share/man \
        /usr/share/doc \
        /usr/share/doc-base

使用 docker build制作可以启动web服务的镜像,别担心,本文绝对原创,明显这里镜像名字使用了Django,其实我本来是想安装django包来启动web服务的,不过Django框架启动web服务稍显麻烦,还得创建project/app之类的,所以偷懒使用Flask来启动。

docker build --force-rm -t python:djangotest-v01 .

可以看到安装了Flask几个依赖之后,镜像从1.02G涨到了1.04G

然后对镜像进行瘦身,这里同样是有两种方式:

  1. Dockerfile 瘦身,缩减镜像大小

新镜像名字tag设置为:
python:djangotest-slim-v01

$ /data/codes/dslim-slim/dist_linux/slim build \
    --expose 8000 \--dockerfile ./Dockerfile \
    --tag python:djangotest-slim-v01 .
  1. 从之前使用docker build制作的镜像基础上进行瘦身
/data/codes/dslim-slim/dist_linux/slim build \
  --expose 8000 python:djangotest-v01

看看瘦身之后的Python镜像吧,我和我的小伙伴都惊呆了!

1.04G --> 55.8M,大小缩减186倍!

两种方式瘦身之后的镜像大小差不多,都是55.8M

$ python3
Python 3.10.12 (main, Sep 11 2024, 15:47:36) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 10400 / 55.8
186.3799283154122

使用curl测试压缩后的python镜像,能够正常返回"Hello,World!"

最后我们再看看针对Java环境的Tomcat容器的镜像精简情况:

下载tomcat镜像(官方镜像441M)

docker pull tomcat:9.0.97-jdk17
tomcat   9.0.97-jdk17   8fffb96a86f6   9 days ago   441MB


使用slim build直接对镜像进行瘦身

/data/codes/dslim-slim/dist_linux/slim \
    build tomcat:9.0.97-jdk17

瘦身后的镜像大小对比:

441M --> 196M

看来Jvm运行环境缩减比例不是很明显,其实如果包括完整JDK的话就将近200M了,想想能压缩成这样也就能够理解了。

这里看瘦身后的容器居然可以bash进来,同样的很多命令都被精简掉了。


每次slim执行之后都会有日志可以查看,日志保存在slim.report.json文件中。

注意

容器瘦身最后得重点来了!

实际测试过程中发现,如果镜像没有对外暴露端口,需要使用【--http-probe=false】参数,但是你会意外的发现镜像会被精简的面目全非,之前的python-3.13版本原来1.02G,缩减之后只有不到30M,python命令本身都无法运行。

前面之所以要启动web服务,是因为slim在缩减镜像是要先把服务起来,这样会加载web服务所有必须的依赖,比如运行web服务的二进制命令(nginx),C的类库,python的依赖包,Java的各种jar,将其保留下来,然后其他的没有用到的几乎都被“优化”掉了,包括系统基本命令和lib库。

所以使用Slim对容器镜像进行瘦身之后还需要经过全面的测试,确保各种必须的依赖没有被删减,在瘦身成功的同时保证服务的正常运行!

(本文完)

Tags:docker 强制删除镜像

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言