docker-pluginを使ってちょっと特殊なアプリケーションをHerokuで動かすための自前imageを作る方法について書きました。間違いなどあればご指摘ください。
Buildpack と Docker
Herokuでは、公式サポート対象の言語で簡単なアプリケーションを動かす場合はgit push
するだけで簡単に済みますが、サポート外の言語でのアプリケーションやデフォルトインストールされていないソフトウェアを使用する場合などは、それ用の実行環境を用意する必要があります。(逆にいうと、それを用意できれば多少特殊なアプリケーションでも動かすことができる、ということになります)
現在、公式サポートされているもの以外の言語・ソフトウェアを使う環境を作る方法としては以下の2種類があります。
Buildpackを作る
これは古くから用いられているもので、アプリケーションをデプロイする際に実行されるスクリプトを用意しておくことで任意の環境を作れる、というものです。実際にはデプロイのたびにソースをダウンロードしてビルドしたりする必要が無いよう、予め対象のソフトウェアをHerokuのCedar Stack環境下でインストールし、そのインストール先ディレクトリごと固めてAmazon S3などに上げておいて buildpackスクリプトではそれをダウンロードして展開するだけ、とするのが定石のようです。
Herokuで公式サポートされている言語環境も、それぞれの言語のバイナリをダウンロードしてきて展開する形でbuildpackが提供されていたりします。
公式でなくとも仕様に沿っていればどんなbuildpackも指定して使うことができるので、そうやって作られたThird-Party Buildpacksも以下で検索したり自分で作って公開しておくことで利用できます。
Docker imageを作る
こちらは2015年5月にリリースされた、比較的新しい方法です。Dockerを使ってCedar Stack環境を簡単に用意でき、その中で動くアプリケーションを開発したらそのimageを(ほぼ)そのままHerokuにデプロイして動かせる、というものです。
Herokuから公式に各言語ランタイムをインストール済みのimageが公開されていて、それらを使うことで各言語のアプリケーションを動かすことができます。
これも自分でimageを作成してデプロイできるので、Cedar Stackのimageを元に自分で使いたい言語やソフトウェアをインストールしたimageを作成すれば、それをデプロイして動かすことができます。
ちなみに公式のDocker imageたちはDockerfile
からのAutomated Buildで作られているので、そのDockerfileを含むリポジトリを読むことで どうやって作られたimageかを知ることができるというのも有り難いですね。
OpenCVインストール済みのDocker imageを作る
先日、画像処理ライブラリOpenCVを使ったアプリケーションをHerokuで動かしたくて、それ用のDocker imageを作りました。以下はそのメモです。
Docker Image of Python with OpenCV 3.0 for Heroku - すぎゃーんメモ
既存のimageから継承
公式で提供されているものを拡張する形でimageを作りたければ、Dockerfileは
FROM heroku/python
のように継承してから追加していけば良さそうです。まったく新しい言語ランタイムをインストールするところから始める場合はheroku/cedar:14
から継承して作っていくことになると思います。
OpenCVのインストール
依存パッケージを入れた上でソースをダウンロードしてきてビルドしていくわけですが、そのへんも含めて各ディストリビューション向けにスクリプト一発で最新のものを入れられるようにしてあるものが公開されています。今回はこれを利用しました。
ただ、そのままではHerokuで動かす用には不都合があったので幾つか変更しています。
インストール先は/app
以下に
重要なこととして、heroku-docker pluginでheroku docker:release
デプロイする際には、imageの内容そのまますべてではなく/app
以下をtar
で固めて作成されたslugというものをアップロードする形になるので、Docker環境内で/usr
以下などにインストールしてもそれは反映されません。
なので、ビルド時のconfigure
オプションで--prefix=/app/.heroku/foobar
と指定してからmake
するなど、/app
以下にインストールするようにする必要があります。Install-OpenCVではcmake
に-D CMAKE_INSTALL_PREFIX=/app/.heroku/opencv
を渡すようにしました。
python2 moduleが有効になるように
heroku/python
を継承した場合、pythonの実行環境は/app/.heroku/python
以下にインストールされていて、そこから使えるようにするためにその場所を教える必要もあるようで、以下もcmake
の引数に追加しました。
-D BUILD_opencv_python2=ON -D PYTHON_INCLUDE_DIR=/app/.heroku/python/include/python2.7
あと、それによって作られるcv2.so
をpythonからロード出来るように、インストールされた先の/app/.heroku/opencv/lib/python2.7/site-packages
をPYTHONPATH
に追加します。
こうして作られたDocker imageを
に置いています。
自前のDocker imageからアプリを作る
これでOpenCVインストール済みのimageが誰でも使えるので、それをベースにアプリケーションを作ってHerokuにデプロイできます。
サンプルアプリケーションを用意してみましたのでお試しください。
$ git clone git@github.com:sugyan/heroku-docker-python-opencv-example.git
$ cd heroku-docker-python-opencv-example
$ heroku create
$ heroku docker:release
Dockerを使う利点
既にBuildpackが提供されていればわざわざDocker imageを作る必要は無いかもしれません。
ただ その内容がちょっと古いものだったり自分の欲しいものと違っていたら、どうしても自分で環境を用意する必要がでてくると思います。
そんな新規に環境を作る際にはBuildpackよりDockerでimageを作るのが良いと思います。Dockerfile
で記述しておいてAutomated Buildされるようにしておけば バージョン変更などの際もDockerfileを変更するだけで修正できるので、自分で再インストールしてディレクトリごと固めてS3に上げ直して…などの手間もないのでラクですよね。
あとやっぱり実際のHeroku環境に近い状態で開発できるのでローカル環境との違いに苦戦したり、が少なくなると思います。
まとめ
Herokuで標準サポートされているもの以外の環境でアプリケーションを動かす方法について、主にDockerを利用する方法、を説明しました。
「こんなWebをアプリ作りたいんだけど、あのライブラリが必要だからHerokuでは無理かなぁ…」という場面でも諦めずに自分で実行環境を用意して動かしてみましょう。