如何实现一个小体积的 js docker 镜像

1次阅读

共计 1089 个字符,预计需要花费 3 分钟才能阅读完成。

在服务端一般使用 node 来运行 js,除了 node 外流行的还有 bun/deno。

但这三个运行时的打包体积都不小,在精简的情况下也在 50 mb 以上,我在这里记录一下我是如何将一个原来使用 node 开发的服务迁移为 3.78MB 的 docker 镜像。

如何实现一个小体积的 js docker 镜像

https://hub.docker.com/layers/llej0/web-font/latest

选择 js 运行时(llrt

要实现这么小的镜像肯定不能再使用 node 这种等级的 js 运行时了,现在最流行的轻量级 js 运行时可以锁定为 QuickJS

我要迁移的项目是我之前写的一个字体裁剪工具 web-font , 它除了纯 js 的部分外还涉及到文件读写和 http server 部分的 api,QuickJS 作为纯粹的解释器是没有这方面的 api 的。

现有的比较成熟的基于 QuickJS 实现的微型 js 运行时有 txiki.jsllrt , 经过实践发现 llrt 可以完美运行在 docker 中,txiki.js 则没那么方便(按照文档编译出来的 tjs 还会依赖其他库)

所以我选择使用 llrt 来作为运行时。

迁移遇到的问题

主要问题是 llrt 没有提供 http 模块(tixiki.js 也是), 幸运的是它提供了 net 模块

所以我基于 net.createServer 手搓了一个 简易 http 服务 和洋葱路由 server.ts

这期间还发现了 llrt 一个 cpu 占用异常:https://github.com/awslabs/llrt/issues/546

打包微小体积的 docker 镜像

1. 代码打包

这方面我使用的是 tsup 将 ts 源码打包为一个 js 文件。

然后使用 llrt compile 命令将 js 文件编译为 .lrt 文件(这一步也能减少差不多 30% 的体积)

2. Dockerfile

得益于 llrt,可以不用依赖任何环境,直接使用 FROM scratch 来得到最小的 docker 镜像体积

FROM scratch
WORKDIR /home/
COPY dist_backend/app.lrt /home/app.lrt
COPY llrt /home/llrt
COPY dist/ /home/dist/
CMD ["/home/llrt", "/home/app.lrt"]

再经过 docker 的压缩后就得到了 3.78MB 这个数字。

使用情况

llrt 的运行速度比 node 还是慢了许多,在我这个场景下它比 node 要慢上两倍,gc 的运行速度也要慢许多。

但初始内存占用和启动速度是碾压 node 的。

由于运行时还不是特别完善的问题,很容易踩坑,所以除非你急需压缩 js 的运行内存占用 / 冷启动速度或者和我一样就是想要这么做,还是建议直接使用 node 吧。

正文完
 0