LoginSignup
3
1

More than 5 years have passed since last update.

monorepoのnpmパッケージをAWS Elastic Beanstalkにデプロイする

Posted at

はじめに

npmパッケージの管理手法の一つにmonorepoがあります。
単一のGitリポジトリの中に、複数のパッケージを置くやり方です。
例えば以下の様なディレクトリ構造をとります。package.jsonが複数あります。

/
  package.json (ルートパッケージのpackage.json)
  packages/ (このディレクトリの下に各パッケージが並ぶ)
    my-web-app/ (子パッケージの一つ)
      package.json
    my-lib/ (これも子パッケージの一つ)
      package.json

この記事では、こうしたmonorepoを採用しているプロジェクトにおいて、ある子パッケージ(Webアプリ)をAWS Elastic Beanstalkにデプロイする際の留意点(トライ&エラー体験談)について書いていきます。
上記の例でいうと、my-web-appをデプロイするケースを考えます。
my-web-appは、兄弟パッケージであるmy-libに依存しているとします。

monorepoやElastic Beanstalk (EB)自体の説明はあまりしません。

どこでeb deployを実行するか

my-web-appをEBにデプロイしたいので、仮にmonorepoでなかったとしたら、普通にmy-web-appをカレントディレクトリとしてeb deployのコマンドを実行するでしょう。

しかし今回はmy-web-appが兄弟のmy-libを参照したいわけです。
my-web-appディレクトリ直下でeb deployをすると、デプロイ先(EC2インスタンス)にはmy-libディレクトリが存在しないわけで、my-web-appを正常に起動できません。

となると、代わりにルートディレクトリ直下でeb deployをして、monorepoを丸ごとデプロイする方法が考えられます。
これならmy-libもデプロイされます。

ルートパッケージのpackage.jsonには、例えば以下の様に書くことになるでしょう。

package.jsonの一部
"scripts": {
  "start": "cd packages/my-web-app && npm start"
}

各パッケージにてnpm installさせるのは困難

monorepoでなかったら、EBにデプロイすると自動的にnpm installが実行されて、次に(デフォルトでは)npm startが実行されるのが、EBの基本の流れですよね。

ところが前節にて、eb deployをするのはmonorepoのルート直下としたので、このままだと各パッケージにおいてはnpm installが実行されません。

単純な対策例として、ルートパッケージのpackage.jsonに以下の様に書くことが考えられます。
postinstallに愚直に書いて、各パッケージでのnpm installの実行を図ります。

package.jsonの一部
"scripts": {
  "postinstall": "npm run install:lib && npm run install:web",
  "install:lib": "cd packages/my-lib && npm install",
  "install:web": "cd packages/my-web-app && npm install"
}

ところがこれはうまく動きません。どうもEBでは、postinstallは実行されないようなのです。
prestartは実行されるようなので、強引ですがそちらで代用することはできます。
(このあたりに言及している参考URLがこちらにあります)

が、仮にprestartにおいてnpm installをさせようとしても、今度はEC2上のファイルシステムのパーミッションの関係で(?)、以下の様にnpm installが失敗します。

EBのnodejs.log抜粋
> cd packages/my-lib && npm install
npm WARN locking Error: EACCES: permission denied, open '/tmp/.npm/_locks/staging-1f97e5e51d5dce3f.lock'
npm WARN locking /tmp/.npm/_locks/staging-1f97e5e51d5dce3f.lock failed { Error: EACCES: permission denied, open '/tmp/.npm/_locks/staging-1f97e5e51d5dce3f.lock'
npm WARN locking stack: 'Error: EACCES: permission denied, open \'/tmp/.npm/_locks/staging-1f97e5e51d5dce3f.lock\'',

結局、自前のnpm scriptsによってnpm installを実行させることはできないのです。
EBの仕組みとして用意されているnpm install(デプロイ直後にルート直下で実行されるnpm install)しかできません。
このあたりの挙動はAWS公式のドキュメントなどで言及している箇所が見つけられず、やってみたらそうなったという結果です。

いっそnode_modules込みでデプロイしちゃおう

以上から、各パッケージの依存性(node_modulesディレクトリ)をデプロイ後にインストールさせるのは難しいことがわかりました。
そこで、もういっそnode_modulesをデプロイ用zipに含めた上で、EBにデプロイする方針を採ります。

大抵の場合、EBにデプロイする時はnode_modulesをzipに含めたくないですから、.ebignoreファイルに以下の様に書くことで除外しているでしょう。

node_modules

今回は逆に含めたいので、単純に上記の記述を削除すればよいです。
もしも、ルート直下のnode_modulesだけはいつも通り除外したければ、例えば以下の様に行頭にスラッシュを書けばよいです。

/node_modules

まとめ

EBはWebアプリを簡単にデプロイできる便利なサービスですが、monorepoとはやや相性が良くないようです。
そこで、各パッケージのnode_modules込みのzipをEBにデプロイすることで、monorepoでもEBの仕組みに乗ることができました。

3
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1