Closed5

Node.jsのSingle Executable Applicationをscrachコンテナで動かす

tttt

Node.js20からSingle Executable Applicationというのが入ったらしく、Node.jsがインストールされていない環境でもNode.jsで書いたアプリケーションを動かせるらしい。

golangみたくscratchコンテナで動かせると面白そうだと思った。

とりあえずこんなのを書いて動かしてみる。

const http = require("http");

const server = http.createServer((req, res) => {
  res.end("Hello World\n");
});

server.listen(process.env.PORT || 8080, () => {
  console.log("Server is running...");
});
FROM node:20-bullseye as builder
COPY sea-config.json .
COPY main.js .
RUN node --experimental-sea-config sea-config.json
RUN cp $(command -v node) /app
RUN npx postject /app NODE_SEA_BLOB sea-prep.blob \
  --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2

FROM scratch
COPY --from=builder /app /app
COPY ./bin/sh /bin/sh
COPY ./bin/libc.so.6 /lib/x86_64-linux-gnu/libc.so.6
COPY ./bin/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
CMD ["/app"]

動かない

./app: error while loading shared libraries: libdl.so.2: cannot open shared object file: No such file or directory
tttt

そもそもNode.jsが依存してる動的リンクライブラリが無いと動かない。それはそう。

tttt

というわけで、

  • Node.jsを自分でビルドする (ビルド時に静的リンクするようにできる)
  • 依存ライブラリをコピーして持ってくる

のどっちか。今回は後者にした。

FROM node:20-alpine as builder
COPY sea-config.json .
COPY main.js .
RUN node --experimental-sea-config sea-config.json
RUN cp $(command -v node) /app
RUN npx postject /app NODE_SEA_BLOB sea-prep.blob \
  --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
FROM scratch
COPY --from=builder /app /app
COPY ./bin/sh /bin/sh
COPY ./bin/libc.so.6 /lib/x86_64-linux-gnu/libc.so.6
COPY ./bin/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
COPY --from=builder /lib/ld-musl-x86_64.so.1 /lib/ld-musl-x86_64.so.1
COPY --from=builder /usr/lib/libstdc++.so.6 /usr/lib/libstdc++.so.6
COPY --from=builder /usr/lib/libgcc_s.so.1 /usr/lib/libgcc_s.so.1
CMD ["/app"]

動いた!

tttt

イメージサイズは103MBだった。でかいな…

$ docker images nodejs-sea
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
nodejs-sea   latest    02b0b6ef0418   4 minutes ago   103MB
このスクラップは2023/05/15にクローズされました