Quantumleap
706 words
4 minutes
NestJS+BunをDockerで動かす

Bun.build#

ビルドすると以下のような感じになります。

.
├── node_modules
├── dist/
   ├── src/
   └── main.js
   ├── package.json
   └── tsconfig.build.tsbuildinfo
├── package.json
├── tsconfig.json
└── tsconfig.build.json

NodeJSでビルドしたときだとnode_modulesdistがあればnode dist/src/mainで起動できました。

Bunの場合はbun dist/src/main.jsで起動できます。Nodeの場合と違って拡張子を指定しなければいけないようです。

Dockerfile#

Bunの公式サイトにDockerfileのドキュメントがあるのでそれを参考にしてみます。

FROM oven/bun:1 AS base

# Development Install
FROM base AS install 
WORKDIR /app/dev
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile

# Production Install
WORKDIR /app/prod
COPY package.json bun.lockb ./ 
RUN bun install --frozen-lockfile --production --ignore-scripts

# Pre Release
FROM base AS prerelease 
WORKDIR /app
COPY --from=install /app/dev/node_modules node_modules
COPY . .

# Test and Build
ENV NODE_ENV=production
RUN bun test
RUN bun run build

途中まで書くとこういう感じになります。

実行時にはdevDependenciesは不要なのですがビルドのときには必要な場合があるのでビルドのときにはDevelopmentの方のnode_modulesを利用します。

なのでPre Releaseのところでは/app/dev/node_modulesの方を使っているわけですね。

そしてもともとあるソースコードを利用してテストとビルドを実行します。

ここのビルドが通れば上で書いたようなディレクトリ構成でトランスパイルされたものが出力されるのでPre Releaseのコンテナは以下のようになるはずです。

app/
├── node_modules
├── src/
   └── main.ts
├── dist/
   ├── src/
   └── main.js
   ├── package.json
   └── tsconfig.build.tsbuildinfo
├── package.json
├── tsconfig.json
└── tsconfig.build.json

ただ、実際にはCOPY . .でディレクトリの全てのファイルをコピーしてきているので余計なファイルも多分に含まれています。余計なファイルを同梱するとイメージのサイズが大きくなるのでそれらは含まないように配慮してリリース用のイメージにコピーします。

リリース用イメージ#

ここで再度公式ドキュメントを参考にコピーするファイルを選定します。

FROM base AS release
WORKDIR /app
COPY --from=install /app/dev/node_modules ./node_modules
COPY --from=prerelease /app/dist/src ./src
COPY --from=prerelease /app/package.json ./package.json
COPY --from=prerelease /app/tsconfig.json ./tsconfig.json

よくわからないのですがBunは実行時にもどうもpackage.jsontsconfig.jsonが必要なので突っ込みました。

あと、ビルドした段階ではNestJSはデフォルトで./distにトランスパイルしたコードが出力されるのですがこれをそのまま突っ込むとモジュールの参照エラーが発生します。

どうもbun run **/main.jsを実行したときのディレクトリからの相対パスが問題っぽくbun run src/main.jsで実行できるようなディレクトリ構造になっていないとダメなようです。

なのでCOPY --from=prerelease /app/dist/src ./srcとしてdist/srcの中身をsrcにコピーするという若干ややこしいことをしています。

NestJS+BunをDockerで動かす
https://fuwari.vercel.app/posts/2024/02/nestjs_bun_docker/
Author
tkgling
Published at
2024-02-15