😎

You installed esbuild for another platform than the one you're cur...

2023/06/16に公開

React+Viteの開発環境をDockerで構築していて、docker-compose upすると以下のエラーが出ました。

エラーログ

You installed esbuild for another platform than the one you're currently using.
This won't work because esbuild is written with native code and needs to
install a platform-specific binary executable.

Specifically the "@esbuild/darwin-x64" package is present but this platform
needs the "@esbuild/linux-arm64" package instead. People often get into this
situation by installing esbuild on Windows or macOS and copying "node_modules"
into a Docker image that runs Linux, or by copying "node_modules" between
Windows and WSL environments.

If you are installing with npm, you can try not copying the "node_modules"
directory when you copy the files over, and running "npm ci" or "npm install"
on the destination platform after the copy. Or you could consider using yarn
instead of npm which has built-in support for installing a package on multiple
platforms simultaneously.

If you are installing with yarn, you can try listing both this platform and the
other platform in your ".yarnrc.yml" file using the "supportedArchitectures"
feature: https://yarnpkg.com/configuration/yarnrc/#supportedArchitectures
Keep in mind that this means multiple copies of esbuild will be present.

Another alternative is to use the "esbuild-wasm" package instead, which works
the same way on all platforms. But it comes with a heavy performance cost and
can sometimes be 10x slower than the "esbuild" package, so you may also not
want to do that.

原因

このエラーは、esbuildのバイナリが、Dockerコンテナのプラットフォーム(おそらくLinux)と一致しないために発生しています。これは、ローカル開発環境(おそらくmacOS)で node_modules をインストールして、それをDockerコンテナにコピーする場合に一般的に見られます。

解決策

  1. Dockerコンテナ内で依存関係をインストール:Dockerfile内で yarn install (または npm install)を実行し、Dockerコンテナ内で依存関係をインストールします。これにより、適切なプラットフォーム用のesbuildバイナリがインストールされます。

  2. node_modulesディレクトリをコピーしないdocker-composeファイルのvolumesセクションで、node_modules ディレクトリをマウントしないようにします。これにより、ホストマシンの node_modulesディレクトリがコンテナ内にオーバーライドされることはありません。

2.のやり方の方がベターなので、こちらを採用します。

修正前(Before)

  • Dockerfile
FROM node:16-alpine

# 作業ディレクトリの設定
WORKDIR /code

# package.json と yarn.lock をコピー
COPY ./package.json ./yarn.lock ./

# 依存関係のインストール
RUN yarn install

# アプリケーションのソースコードをコピー
COPY . .

# アプリケーションを起動するコマンド
CMD ["yarn", "dev"]

  • docker-compose.yml:
version: '3'

services:
  front:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./:/code
    ports:
      - "3000:3000"

修正後(After)

volumesの箇所を修正

volumes:
  - ./:/code
  - /code/node_modules

2行目の- /code/node_modulesは、node_modulesディレクトリを無名ボリュームとして扱うことで、ホストとの同期を防ぎます。

この方法では、コンテナ内のnode_modulesディレクトリがホストのディレクトリとは独立して扱われ、ホストから分離されます。

Discussion