結論
gcr.io/distroless/static-debian12
ではなくgcr.io/distroless/base-debian12
を使え!
はじめに
Bun、速くて身軽で快適ですよね。
もはやyarnやpnpmなどのパッケージマネージャは不要だし、ランタイム同梱のバイナリまで生成してくれるのでDockerfile職人にも優しいです。
しかし今回、一部のdistrolessイメージではBunが生成するバイナリを動かせないという事象に遭遇したため、解決方法と共にこちらに残しておきます。
使用したDockerfile
FROM oven/bun:1 as install
WORKDIR /temp/build
COPY package.json bun.lockb /temp/build/
RUN bun install --frozen-lockfile
FROM install as build
COPY . .
RUN bun run compile
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /temp/build/app /
ENTRYPOINT [ "/app" ]
bun run compile
はbun build --compile src/index.ts --outfile ./app
と読み替えてください。
これを以下のdockerコマンドで実行すると、
$ docker build --no-cache -t myapp .
$ docker run --init -t myapp
exec /app: no such file or directory
エラーが出てしまいました。
原因
/app
は確かに存在するし、実行ファイルであることには間違いないのにno such file or directory
と言われてしまいます。
結論から言うと、エラーの原因は「distrolessのstaticイメージにはglibcが含まれていない」ことだったようです。
なので、先ほどのDockerfileの最終ベースイメージのgcr.io/distroless/static-debian12
をgcr.io/distroless/base-debian12
に置き換えると動くようになります。
補足
/app
は確かに存在するし、実行ファイルであることには間違いないのにno such file or directory
と言われてしまいます。
と述べましたが、何も説明せずに言い切ってしまうのは無責任だと思うので実施した調査方法を共有しておきます。
実は、各distrolessイメージにはdebugタグが用意されており(参照)、通常のイメージには含まれていないシェルなどが同梱されています。こちらのタグを利用すればdocker run -it
でコンテナ内に潜り込んで調査できるというわけです。