LoginSignup
0
0

More than 1 year has passed since last update.

DjangoをDockerでHerokuにデプロイする

Posted at

python+conda以外の全ての知識がなかったのでかなり苦労してdjango+docker+heroku環境を整えた。

今回は化合物のSMILESを入力として受け取り、その化合物を表示するところまで行きます。

参考にしたサイト様

Docker上でAnacondaを使って入れたDjangoをHerokuで動かす
HerokuにConda環境で開発したアプリをデプロイする方法
Django 入門

環境

Window 11
anaconda
VScode

1. Dockerでコンテナを作成する。

Docker上でAnacondaを使って入れたDjangoをHerokuで動かすの2,3,4,5を参照してください。condaの仮想環境に入った後にインストールするものはanacondaからdjango環境を作ると同じものを入れてください。

最後にdocker commit django djangotest:1.0.0などで適当にdockerを保存しておきます。

2. anacondaからdjango環境を作る。

名前は何でもよいのでwindows 11環境でdjango環境を作ります。(anaconda環境の作成は省略)
rdkitはお好みでインストールしてください。普通のアプリ作るならいらないです。

bash
(base)       > conda create -n django_env python==3.7
(base)       > conda activate django_env
(django_env) > conda install django=3.* -c conda-forge
(django_env) > conda install -c rdkit -c conda-forge rdkit
(django_env) > conda install django-heroku -c conda-forge

次にdjangoでアプリケーションを作ります。

プロジェクト名:wepapps、アプリ名:chem_appで作ります。

bash
(django_env) > mkdir django_sample
(django_env) > cd django_sample
(django_env) > mkdir webapps
(django_env) > cd webapps
(django_env) > django-admin startproject webapps .
(django_env) > python manage.py startapp chem_app

django-admin startproject webapps .は、mkdir webappsと同じ名前である必要はないです。

ここで一旦python manage.py runserver 0.0.0.0:8000として動くかどうかを確認します。

3. アプリケーションを作る

django_sample/webapps/webapps/setting.pyで、以下を変更。

setting.py

# herokuでアクセスできるようにしておく
ALLOWED_HOSTS =  ['127.0.0.1', '.herokuapp.com']

~

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [  
            # htmlを読み込めるようにしておく。
            os.path.join(BASE_DIR, 'chem_app/templates'), ## <- ココを追加
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

次にdjango_sample/webapps/webapps/urls.pyを以下のように変更する。

urls.py
from django.conf.urls import url, include
from django.contrib import admin
from django.urls import path
import chem_app.views as chem # django_sample/webapps/chem_app/views.pyをchemとして扱っています

urlpatterns = [
    path('admin/', admin.site.urls),
    path('smiles2picture/', chem.smiles2pic, name='smiles2picuture'),
    path('smiles2picture/result', chem.smiles2pic_result, name='s2p_res'),
]

django_sample/webapps/chem_app/views.pyを以下のように変更する。

views.py
from django.shortcuts import render
from django.http import HttpResponse  # Load Module
from rdkit import Chem
from rdkit.Chem import Draw
import base64
from io import BytesIO
from PIL import Image
import os

def pil_to_base64(img, format="jpeg"):
    buffer = BytesIO()
    img.save(buffer, format)
    img_str = base64.b64encode(buffer.getvalue()).decode("ascii")

    return img_str

def smiles2pic(request):
    return render(request,"smiles2picture.html")

def smiles2pic_result(request):
    # SMILESから画像を生成する
    smiles = request.POST.get("SMILES", None)
    print(f"smiles:{smiles}")
    m = Chem.MolFromSmiles(smiles)
    img = Draw.MolToImage(m,size=(300, 300))
    img_base64 = pil_to_base64(img, format="png")
    return render(request, 'chemtest.html',{"title":smiles,"img":img_base64})

django_sample/webapps/chem_app/templates/smiles2picture.html及びをdjango_sample/webapps/chem_app/templates/chemtest.html以下のようにして追加する。

smiles2picture.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Smiles2Picture</title>
</head>
<body>
    <p>化合物のSMILESを入力</p>
    <form action="/smiles2picture/result" method="POST">
        {% csrf_token %}
        <input type="text" name="SMILES">
        <input type="submit" value="送信">
    </form>
</body>
</html>
chemtest.html
<!doctype html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>{{ title }}</title>
    </head>
    <body>
        <img src="data:image/png;base64,{{img}}">
    </body>
</html>

ここではrdkitで生成した画像をファイルに保存せずにbase64にして直接htmlファイルに渡していますが、これはherokuがファイルの保存して使いまわすようなことができないからです。staticな場合にはdjangoの方でちょっと面倒な操作が必要みたいです。

ここでもう一度python manage.py runserver 0.0.0.0:8000を打って http://127.0.0.1:8000/smiles2picture/ にアクセスしてきちんと動くか確認します。

4.Dcokerfileを生成する。

django_sample直下にはDockerfileを設置します。

Dockerfile
# 自分のdockerイメージに書き換える
FROM djangotest:1.0.2

SHELL ["/bin/bash", "-c","-l"]

RUN echo "chmod 777 /root/.pyenv/versions/miniconda3-latest/etc/profile.d/conda.sh" >> ~/.bashrc
RUN echo "source /root/.pyenv/versions/miniconda3-latest/etc/profile.d/conda.sh" >> ~/.bashrc
RUN echo "conda activate base" >> ~/.bashrc
RUN echo "conda activate django" >> ~/.bashrc
RUN echo "conda env list" >> ~/.bashrc

ENV PATH /root/.pyenv/versions/miniconda3-latest/envs/django/bin:$PATH

COPY webapps/ ~/webapps
WORKDIR ~/webapps
CMD gunicorn --bind 0.0.0.0:$PORT webapps.wsgi

5. herokuの導入。

gitが入っている必要があり。
公式サイトから自環境にあったものを選択して導入。
それからheroku CLIを入れる。windowsだと割と何も考えずにできる。

6. herokuでpushする。

herokuへpush
heroku container:login
heroku create myappname
heroku container:push web -a myappname
heroku container:release web -a myappname

これでherokuに適用されたはずです。自分の作ったサイトにアクセスして動くか確かめてみましょう。

だめならheroku logs --tail -a myappnameでログが確認できます。

私の作ったサイトを仮公開しておきます。https://mychemodel2.herokuapp.com/smiles2picture

補遺・最終的なディレクトリ構造

ディレクトリ構造
DJANGO_SAMPLE
│  Dockerfile
│
└─webapps
    │  db.sqlite3
    │  manage.py
    │
    ├─chem_app
    │  │  admin.py
    │  │  apps.py
    │  │  models.py
    │  │  tests.py
    │  │  views.py
    │  │  __init__.py
    │  │
    │  ├─migrations
    │  │      __init__.py
    │  │
    │  ├─static
    │  │  └─chem_app
    │  │      └─images
    │  │          └─  test.png
    │  │
    │  └─templates
    │         chemtest.html
    │         index.html
    │         smiles2picture.html
    │  
    └─webapps
        │  asgi.py
        │  settings.py
        │  urls.py
        │  wsgi.py
        └─ __init__.py
0
0
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
0
0