HerokuにConda環境で開発したアプリをデプロイする方法

#はじめに
Conda+RDkit等を使って作成したアプリをHerokuにデプロイしたいと思い、色々試行錯誤した結果、Dockerを使って、2日がかりでなんとかデプロイするところまでできたのでメモっておく。

#環境
今回は以下の構成で構築したアプリの配布を確認した。
- Windows 10
- python 3.7
- django 3系 (WEBアプリフレームワーク)
- Pytorch 1.7 cpu版 (ディープラーニングフレームワーク)
- RDKit (ケモインフォマティクスライブラリ)
- gunicorn (WEBサーバ)
- herokuアプリケーション名: chemodel

#今回配布したいアプリ
## ソース
今回は、Condaの仮想環境上でのRDKitというライブラリの動作を確認できればよかったので、ある化合物をRDkitで読み取りその原子番号を表示するという、超簡単なDjangoアプリを作成した。
Djangoアプリのviews.pyを以下に示す。

``` chemodel/chemodel_app/vies.py
from django.shortcuts import render
from django.http import HttpResponse  # モジュールの読み込み
from rdkit import Chem


def hellofunction(request):
    m = Chem.MolFromSmiles('Cc1ccccc1')
    data = len(m.GetAtoms())
    return HttpResponse('RDkitアプリだよ!!!!! 原子数＝{0}'.format(data))
```

## 動作イメージ
動作イメージは、見せるまでもないが、こんな感じとなる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329816/5415364b-29dd-a755-5ffd-38c279865a0a.png)

# なぜDockerか
Conda環境を必要とするアプリのHerokuへの配布方法としては、conda--buildpack (https://elements.heroku.com/buildpacks/conda/conda-buildpack) を用いた方法があるが、そもそもローカルとHerokuでは、OSアーキテクチャーが異なるため、Windowsではインストールできたバージョンの組み合わせが、Herokuではインストールできない(Condaのリポジトリにそのアーキテクチャーのバージョンが存在しない）ケースが多発するからである。Dockerであればローカルでビルドした組み合わせをそのまま配布できるため、確実だからである。

#手順
ここから実際にデプロイするまでの手順を示す。Heroku CLI はインストールされている前提とする。

## Herokuレジストリへのログイン

以下のコマンドによりログインする。

```sh

$ heroku container:login
```

## Herokuアプリケーションの作成
Herokuアプリケーションを作成する。
勿論、実際のDjangoアプリは、開発されている前提とする。


```sh
$ heroku create chemodel
```

## Dockerファイルの作成

以下のようにDockerファイルを作成する。

```Dockerfile
FROM continuumio/miniconda3

RUN conda create -n chemodel python==3.7 

SHELL ["conda", "run", "-n", "chemodel", "/bin/bash", "-c"]

RUN conda install django=3.* -c conda-forge --override-channels
RUN conda install pytorch==1.7.1 torchvision==0.8.2 torchaudio==0.7.2 cpuonly -c pytorch -c conda-forge --override-channels -c tboyer
RUN conda install -c rdkit -c conda-forge rdkit --override-channels
RUN conda install -c rdkit -c conda-forge mordred --override-channels
RUN conda install django-heroku -c conda-forge --override-channels

# pip 
RUN pip3 install --upgrade pip
RUN pip3 install gunicorn

# Add our codeg
ADD ./chemodel /chemodel/

WORKDIR /chemodel
CMD gunicorn --bind 0.0.0.0:$PORT chemodel.wsgi

```

Dockerファイルは、[Miniconda on Heroku Example App](https://github.com/heroku-examples/python-miniconda)を参考にしているのだが、少し解説する。
- まず、```FROM～```のところで、minocondaのベースイメージを指定する。ここは、Herokuのサンプル (https://github.com/heroku-examples/python-miniconda) では、Pythonがバージョン2のようであり、サンプルアプリがうまく動かなかったので変更している。
- 続いて、```RUN conda create -n chemodel python==3.7 ```で、作成したいPythonのバージョンでConda仮想環境を作成する。
- ```SHELL～```の行でその仮想環境をActivateする。
- conda, pipで各自インストールしたいものを列挙する。
- ```ADD～``` の行では、自分が配布したいアプリを、コンテナ側の/chemodelというフォルダにコピーする。
- ```WORKDIR～```で、アプリのフォルダに移動し、```CMD～```でアプリを起動している。$PORTというのは、herokuでDockerを配布する際のポート指定の際に必要となる書き方である（参考文献参照)

## コンテナのプッシュ
Djangoプロジェクトフォルダが直下にあるフォルダに、Dockerfileを配備し、そのフォルダ上で以下コマンドを実行する。-aオプションは、各自のheroku アプリ名に読み替えてほしい。

```
$  heroku container:push web -a chemdel
```

## コンテナのリリース
ビルドが成功したら、以下のコマンドでリリースできる。-aオプションは、各自のheroku アプリ名に読み替えてほしい。

```
$  heroku container:release web -a chemodel
```

これで、ブラウザでherokuアプリのURLを叩くと、アプリの画面が確認できるはずだ。



#おわりに
**RDkitアプリだよ!!!!! 原子数＝7**

たったこれだけだが、これが表示された瞬間は嬉しかった。今回の方法を使ってどんなアプリをデプロイするか、考えるだけでもワクワクしてくる。


#参考文献
- [Heroku Container Registry および Runtime (Docker デプロイ)](https://devcenter.heroku.com/articles/container-registry-and-runtime#dockerfile-commands-and-runtime)

- [Miniconda on Heroku Example App](https://github.com/heroku-examples/python-miniconda)

- [Docker Hub continuumio/miniconda3](https://hub.docker.com/r/continuumio/miniconda3)