最近将一个 Spring Boot 项目编译成了 Spring Native 可执行文件,项目启动速度是上来了,但是可执行文件的大小可骤增至 350M 左右,导致 Docker 镜像的大小也一起增加了很多,考虑到 Docker 拉取本身的网络就很坎坷了,我就想有没有办法能再压缩下大小。
最开始的方案是使用 upx, 压缩率不错,压缩后可直接执行,但是发现这个工具是有代价的,因为他是执行时从内存中解压你原本的程序,所以你节省了多少可执行文件大小,就会额外占用多少内存,这对我是不可接受的,我觉得内存更可贵一些,这个方案可能更适合 go 程序使用,本身可执行文件大小不会太大,所以也不会导致增加很多内存占用。
第二个方案是无意中想到的,我能不能自己压缩文件放到镜像中,然后在运行时解压出来再执行,这相较于 upx 的方案来说是在硬盘解压,不会额外占用内存,但是这个要考虑解压的速度(压缩速度不是很重要,可以用 CI/CD 来跑),然后就找到了一个压缩算法 zstd,不论压缩率设置多高,解压缩的时间都是一样的 (如 350M 使用 zstd -19 最高级别,压缩时间 5 分钟,大小可达到 80M 左右,但解压时间仅 0.5 秒)。
然后在 Dockerfile 中给镜像安装 zstd ,并在最后运行时进行判断是否解压:
FROM debian:10-slim
ARG TARGETARCH
RUN apt update -y && apt install --no-install-recommends zstd -y && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# 省略其他
CMD if [ -f /data/app.zst ]; then zstd --no-progress -d /data/app.zst && rm -rf /data/app.zst && chmod +x /data/app && /data/app --spring.config.location=file:/root/application.properties; else chmod +x /data/app && /data/app --spring.config.location=file:/root/application.properties; fi
不知道这种方式算优雅,还是算丑陋,但至少解决了我的问题,希望也能帮助到有类似需求的人。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.