Docker Compose で初回起動時のみ yarn install を実行させる方法

Bash,Docker

はじめに

Docker Compose の初回起動時のみ、ライブラリのインストールを実行したい場合があります。

  • NodeJS の場合 yarn installnpm install
  • PHP の場合 composer install
  • Ruby on Rails の場合 bundle install

いい方法が無いか考えた末、 docker-compose.yamlcommand 属性に工夫して解決させてみました。

検証環境

$ docker-compose --version
docker-compose version 1.29.0, build 07737305

Docker Compose 初回起動時にライブラリをインストールしておかないとどうなる?

例えば、以下のような NodeJS の Web アプリケーションを起動させたいと思います。

yarn start というコマンドでサーバが起動します。

version: "3.4"

services:
  nodejs:
    image: node:15.13.0-alpine
    volumes:
      - .:/app:cached
    working_dir: /app
    entrypoint:
      - sh
    command:
      - -c
      - |
        yarn start
    ports:
      - 3000:3000

entrypointcommand の設定情報から、起動時に以下のコマンドが実行されます。

$ sh -c 'yarn start'

この設定でアプリケーションを起動してみます。

$ docker-compose up

エラーとなってしまいました。
理由は単純で、 node_modules ディレクトリがないため、つまり yarn install コマンドを実行し、ライブラリをインストールしていないためです。

Docker Compose 初回起動前に yarn install しておけばいいが。。。

Docker Compose 起動前に yarn install を実行しておけば、 node_modules ディレクトリにライブラリがインストールされますが、こんなことを考えながらローカル開発環境を構築したく有りません。

初回のみ yarn install が自動的に実行させるようにするにはどうしたら良いでしょう?

Docker Compose 初回起動時のみ yarn install が実行させるようにする

command 属性に 3 行追加し、初回起動時のみ yarn install が実行されるようにしてみました。

version: "3.4"

services:
  nodejs:
    image: node:15.13.0-alpine
    volumes:
      - .:/app:cached
    working_dir: /app
    entrypoint:
      - sh
    command:
      - -c
      - |
        [ -f ~/.exec-once ] || {
          yarn install && touch ~/.exec-once
        }
        yarn start
    ports:
      - 3000:3000

ロジックを簡単に解説すると以下のようになります。

  1. ~/.exec-once ファイルが存在するかをチェック
  2. 存在していなかった場合は以下の処理を実行
    • yarn install コマンドを実行
    • ~/.exec-once ファイルを作成
  3. yarn start コマンドを実行

2 の処理は初回起動時しか実行されません。

yarn install だけではなく、 bundle installcomposer install にも利用できるはずです。

ひとこと

小細工でしのぎましたが、他のエンジニアの方々はどうやって対処しているのでしょう?

「こんなふうに実装するのがよい」というアドバイスが有れば是非教えて下さい。

Bash,Docker