LoginSignup
4
1

More than 3 years have passed since last update.

herokuでbuildpackを自作してがんばってデプロイできるようにする

Posted at

概要

  • Herokuではデプロイするためにbuildpackというのを使う
    • Node.jsではnpm scriptstartを定義しておけば、あとはいい感じにやってくれて嬉しい
    • よくある構成のアプリだと、簡単にデプロイできる一方で、独自のオレオレ構成アプリはデプロイが大変!(ていうかどうやるんだろう)
  • buildpackを自作してしまったらよいのでは?
  • 試しにやったら結構苦労した

想定される構成

フロントエンド(SPAの静的なファイル)とバックエンド(WebAPI)の組み合わせです。
Herokuでは静的なファイルを配信するためにもNginxやそれに類する静的ファイル配信用のアプリケーションを用意して、そこで配信する必要があります。
ここで、この問題に対応するためには以下のようなソリューションが考えられるでしょう。

  1. WebAPIの特定のパスにアクセスする場合は静的ファイルを配信できるように実装する
  2. 静的ファイルはNetlifyとかで配信して、HerokuではWebAPIだけ載せる(CORS対策ちゃんとする)
  3. Dockerイメージに固める
  4. Herokuのインスタンス内に2つのプロセスを立ち上げて、静的ファイル配信とWebAPIを共存させる

1, 2はダルかったので、3か4で、おそらく簡単で正しいのは3なのだと思うのですが、buildpackを理解する上でもやっておこうと思い、4を選びました。

実施内容

実際の構成

こんな感じでhttp-serverでリクエストを受けて、それをWebAPIと静的ファイル配信に振り分ける感じです。
image.png

自作のbuildpackを使えるようにする

まずは、buildpackを作る前にオレオレbuildpackを使えるようにする方法を確認します。
HerokuのBuildpack APIが参考になるでしょう。
具体的なところは実際のbuildpack(heroku-buildpack-nodejs)をみた方が早かったです。

それを踏まえた上で、自分がやったことは以下の通りです。

  • Githubとかにbuildpack用のリポジトリを用意する(今回はアプリのリポジトリをそのまま使うことにした)
  • トップレベルにbinディレクトリを用意する
  • binディレクトリにはdetect, compile, releaseというシェルスクリプトを用意する
  • detectで"Monorepo"を出力する
  • compileでビルドやサーバーを用意する
  • releaseは特になにもしなくていいっぽい

compileでやったこと

実物はこちらです。
https://github.com/naoki-tomita/todo-wasm/blob/master/bin/compile
言語はRustなので、それ特有の処理もやっています。

  • Rust関連のツールをインストールする先を$CACHE_DIRに設定しておく(ここのディレクトリは永続されるっぽいので、次回以降は早くなる)
  • rustupというバージョン管理ツールをインストールする
  • cargo-webというツールをインストールする
  • ビルドされた成果物が$CACHE_DIRに出力されるように設定する(次回からはインクリメントビルドが効く)
  • フロントエンド、バックエンドをビルドする
  • ビルドで生成された成果物を$BUILD_DIRにコピーしておく(Herokuのインスタンスには、$BUILD_DIRがコピーされるのでやっとかないと意味ない)
  • Node.jsを$BUILD_DIR/.heroku/node下にインストールする(http-serverを立てるのに必要だった)
    • インストールというか、Linux用の実行ファイルを公式サイトからダウンロードして解凍しただけ。

.profile.dを用意する

.heroku/node下にNode.jsをインストールしましたが、当然ながらこれだけでは実行することができません。
パスを通さないといけないのです。しかし、パスを通す方法がわからず、相当苦戦しました。

結論からいうと、.profile.dというフォルダ下(binと同じ階層)に任意のシェルスクリプトを置いておくことで、.bash_profile的な効果を得られるようです。
そこで、$HOME/.heroku/node/binにパスを通すことで、nodeコマンドやnpmコマンドを利用できるようにしました。

Procfileを用意する

Herokuでは、トップレベルの階層にProcfileというファイルを置いて、中にコマンドを書いておけば起動時に実行されます。
したがって、これを使ってhttp-serverとWebAPIを起動することにしています。

できたものがこちらになります。

以上です。よろしくお願いします。

4
1
0

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
4
1