WebエンジニアのLoL日記

LoLをプレイしたりLJLの試合を見たりするのが好きなエンジニア。LoLのイベントやパッチノートなど気になった点を記事にしたり、LJLについの記事をかいたりしています。某社でWeb系のエンジニアとして働いているので、技術系の記事もたまに書きます。コンタクトを取りたい場合はtwitterまで。

Dockerではなくてheroku.ymlを使ってPython2とOpenCVの環境をHeroku上に整える

はじめに

HerokuでOpenCVを扱いたい場合、従来はDockerfileを用意してデプロイする必要がありましたが、heroku.ymlの登場によりよりお手軽にデプロイできるようになりましたので紹介します。

環境

OpenCVを使わない場合のPython Flask アプリケーションのデプロイ

Herokuは、GitHubのように、Heroku上のリポジトリソースコードをPushすると自動的にビルドしてWebアプリケーションを公開してくれます。

今回はPythonのFlaskというWebフレームワークを利用してWebサービスを公開しようと思っています。まずはOpenCVを使わない場合を考えます。Flaskのアプリケーションをデプロイする場合、リポジトリのrootに以下の3つのファイルが必要です。

  • runtime.txt
  • requirements.txt
  • Procfile

また以上の3つのファイル以外に当然アプリケーションのコードが必要です。順に簡単に説明します。

アプリケーションコード

まずアプリケーションコード(Flask)の本体として main.py を用意します。今回は凄くシンプルなものを用意しました。

# -*- coding: utf-8 -*-

import os
from flask import Flask

@app.route("/")
def index():
    return "Hello Flask"

if __name__ == "__main__":
    port = int(os.environ.get("PORT", 5000))
    app.run(port=port, debug=True)

Herokuでアプリケーションを動かす場合は、シェルの環境変数で指定されたポートで動かす必要がありますので、なんらかの方法でポート番号をPythonに渡してやる必要があります。今回はPythonのコード上でシェルの環境変数からポート番号を取ってくるようにしています。

runtime.txt

runtime.txt の中身は以下の通りです。

python-2.7.14

アプリケーションコードの実行環境を書くだけです。

requirements.txt

Pythonの場合必要なやつです。pipでインストールするやつを書きます。

Flask==0.10.1
gunicorn==19.7.0

こういう感じで。

Procfile

Webアプリケーションの起動方法を書きます。今回はこういう感じになります。

web: gunicorn app:app --log-file=-

デプロイ

これらのファイルを配置します。

$ ls
app.py          Procfile          runtime.txt           requirements.txt

git remoteにherokuが追加されていることを確認してpush(herokuの追加方法はここでは省略)。

$ git remote -v
heroku  https://git.heroku.com/xxxxx.git (fetch)
heroku  https://git.heroku.com/xxxxx.git (push)

$ git push heroku master

これで xxxx.herokuapp.com にアクセスすると Hellow Flask が動くはずです。

このままだとOpenCVが使えない

このままだとopencvは使えません。python-opencv自体はrequirements.txtに追加すれば利用できるようになるのですが、opencv本体がheroku側にインストールされていないので動かないのです。

Flask==0.10.1
gunicorn==19.7.0
numpy==1.13.1
opencv-python==3.3.0.10

ではどうしたらいいのでしょうか。

従来はDockerを使ってデプロイしていました。

従来はDockerを使ってデプロイしていました。

qiita.com

しかしDockerは触れたことがない人にはなかなか難解ですし、とくにherokuのDockerデプロイはかなり難解でした。僕は結局Dockerを使ってのデプロイ方法が分からず投げました。

Dockerの変わりにheroku.yml が使える

実は、heroku.yml を書くと、Dockerを利用しなくても、opencvがインストールされている環境を簡単にheroku上に用意できることがわかりました。

heroku.yml とは

公式の解説はこちらです。

devcenter.heroku.com

公式のサンプルはこのようになっています。

build:
  languages:
    - ruby
  packages:
    - imagemagick
run:
  web: bundle exec puma -C config/puma.rb

heroku.ymlでOpenCVが動くheroku環境を構築する

公式の解説を読むと、Procfileのかわりにheroku.ymlを用意しろと書いてありました。そこで、herokuでPython2 + OpenCVを動かすにはこうします。

build:
  languages:
    - python
  packages:
    - libopencv-dev
run:
  web: gunicorn app:app --log-file=-

packages のところにlinopencv-devを書くと、デプロイ時にapt-get installOpenCVがインストールされます。これでOpenCVが使えるようになります。Dockerfileよりもずっと簡単ですよね。

Procfileの中身はheroku.ymlrunの所に書いてありますので、これでProcfileは必要なくなりましが、runtime.txtrequirements.txtは必要なので注意してください。また。Procfileheroku.ymlが両方存在する場合、heroku.ymlが優先されるので、一旦Procfileは消さずに放置しておいても構いません。

デプロイ方法は、heroku.ymlリポジトリのルートディレクトリに置いてpushするだけです。今回はとりあえずProcfileはそのままデプロイしました。

$ ls
app.py          heroku.yml          Procfile          runtime.txt           requirements.txt

$ git add heroku.yml
$ git commit

$ git remote -v
heroku  https://git.heroku.com/xxxxx.git (fetch)
heroku  https://git.heroku.com/xxxxx.git (push)

$ git push heroku master

pushすると、runtime.txtを元にpython2がインストールされ、heroku.xmlを元にpackagesがインストールされ、requirements.txtが解決されたうえでアプリケーションが起動します。パッケージのインストールなどが挟まるのでデプロイ時間は結構長くなってしまうのですが、Dockerfileよりも断然お手軽です。

OpenCV以外もheroku.ymlでインストールできるパッケージは多数あると思うので是非ためしてみてください。

まとめ

まだdeveloper preview版ですが、heroku.ymlを使い、Dockerを使うことなくheroku上にOpenCV環境を整える方法を紹介しました。かなりざっくりで、本当はちゃんとリポジトリとか公開できると良いのですが、僕もまだちょっと試したばかりなので公開できるようなものがありません><。もし漏れなどありましたらご指摘頂ければと思います。(公式のドキュメントみるとまだPython対応してないようで、もしかしたらDockerコンテナのpushとかも必要?)

Herokuは規模小さなアプリケーションのデプロイであれば無料で使えますので、ぜひ活用してみてください。

詳解 OpenCV ―コンピュータビジョンライブラリを使った画像処理・認識

詳解 OpenCV ―コンピュータビジョンライブラリを使った画像処理・認識