Heroku
AdventCalendar
docker
HerokuDay 7

HerokuでOpenCVを使うためのdocker imageの作り方

More than 3 years have passed since last update.

docker-pluginを使ってちょっと特殊なアプリケーションをHerokuで動かすための自前imageを作る方法について書きました。間違いなどあればご指摘ください。

Buildpack と Docker

Herokuでは、公式サポート対象の言語で簡単なアプリケーションを動かす場合はgit pushするだけで簡単に済みますが、サポート外の言語でのアプリケーションやデフォルトインストールされていないソフトウェアを使用する場合などは、それ用の実行環境を用意する必要があります。(逆にいうと、それを用意できれば多少特殊なアプリケーションでも動かすことができる、ということになります)

現在、公式サポートされているもの以外の言語・ソフトウェアを使う環境を作る方法としては以下の2種類があります。

Buildpackを作る

https://devcenter.heroku.com/articles/buildpacks

これは古くから用いられているもので、アプリケーションをデプロイする際に実行されるスクリプトを用意しておくことで任意の環境を作れる、というものです。実際にはデプロイのたびにソースをダウンロードしてビルドしたりする必要が無いよう、予め対象のソフトウェアをHerokuのCedar Stack環境下でインストールし、そのインストール先ディレクトリごと固めてAmazon S3などに上げておいて buildpackスクリプトではそれをダウンロードして展開するだけ、とするのが定石のようです。

Herokuで公式サポートされている言語環境も、それぞれの言語のバイナリをダウンロードしてきて展開する形でbuildpackが提供されていたりします。

https://devcenter.heroku.com/articles/buildpacks#officially-supported-buildpacks

公式でなくとも仕様に沿っていればどんなbuildpackも指定して使うことができるので、そうやって作られたThird-Party Buildpacksも以下で検索したり自分で作って公開しておくことで利用できます。

https://elements.heroku.com/buildpacks/

Docker imageを作る

https://devcenter.heroku.com/articles/docker

こちらは2015年5月にリリースされた、比較的新しい方法です。Dockerを使ってCedar Stack環境を簡単に用意でき、その中で動くアプリケーションを開発したらそのimageを(ほぼ)そのままHerokuにデプロイして動かせる、というものです。

Herokuから公式に各言語ランタイムをインストール済みのimageが公開されていて、それらを使うことで各言語のアプリケーションを動かすことができます。

https://hub.docker.com/u/heroku/

これも自分で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のインストール

依存パッケージを入れた上でソースをダウンロードしてきてビルドしていくわけですが、そのへんも含めて各ディストリビューション向けにスクリプト一発で最新のものを入れられるようにしてあるものが公開されています。今回はこれを利用しました。

https://github.com/jayrambhia/Install-OpenCV/

ただ、そのままではHerokuで動かす用には不都合があったので幾つか変更しています。

インストール先は/app以下に

重要なこととして、heroku-docker pluginheroku 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-packagesPYTHONPATHに追加します。

こうして作られたDocker imageを

https://hub.docker.com/r/sugyan/heroku-python-opencv/

に置いています。

自前のDocker imageからアプリを作る

これでOpenCVインストール済みのimageが誰でも使えるので、それをベースにアプリケーションを作ってHerokuにデプロイできます。
サンプルアプリケーションを用意してみましたのでお試しください。

https://github.com/sugyan/heroku-docker-python-opencv-example

$ 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では無理かなぁ…」という場面でも諦めずに自分で実行環境を用意して動かしてみましょう。