Git clone後のdocker初回起動時の/bin/sh: xxx: not foundエラーへの対応
概要
npm や yarn でパッケージ管理しているプロジェクトで、node_modulesを共有していない場合(通常しないと思いますが)、既存プロジェクトをcloneなどで取得してきた場合、docker 初回起動時に、次のようなエラーが出力されます。
- 前提:docker-compose.yml 内で
yarn devの起動を指定している
FROM node:17-alpine
WORKDIR /usr/src/app
version: '3'
services:
node:
build: ./
volumes:
- ./node:/usr/src/app
command: sh -c "cd site && yarn dev"
ports:
- "3000:3000"
- Git からソースコードを
cloneしてきて、そのままdocker-composeを実行
docker-compose up -d
- docker コンテナが起動しないので、ログを確認
docker-compose logs node
- 依存パッケージを使用するコマンドが見つからずにエラーとなっている。
yarn run v1.22.17
/bin/sh: next: not found
$ next dev
error Command failed with exit code 127.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
発生理由
これは、npm または yarn で、package.jsonに基づいて、依存パッケージを管理をしていて、node_modules内のファイルは Git 管理していないため、初回起動時にコマンドが通らずにエラーが発生します。
※そうなると、DockerFile 内の指定で、RUN cd site && yarn installのように依存関係にあるパッケージをインストールしたいと考えますが、ビルド実行時点では、docker-compose.yml側でvolumesで指定しているでフォルダは、まだマウントされていないため、フォルダが見つからず、このパターンもエラーになります。
対応策
Git からcloneしてきた後の初回起動時には、docker-compose up -dする前に、docker-compose runコマンドを実行して、依存パッケージをインストールすることで解消できます。
docker-compose run -w /usr/src/app/site --rm node yarn install
docker-compose up -d
※-wオプションにはパッケージをインストールする対象のフォルダ(コンテナ内でのパス)を設定
※--rm nodeに続いて、実行させたいインストールコマンドを設定
所感
docker-compose.yml側で初回かどうかを判定・分岐してyarn install等を行うパターンもあるようでしたが、Dockerfileやdocker-compose.ymlはなるべく定義型で済ませておきたい(シェル的な処理を書きたくない)のと、初回作業の話のみとなるので、初回導入時にdocker-compose run ・・・を実行する手順としておくことで、特に問題ないかと思います。
Discussion