Herokuの無料枠が無くなったので、デプロイ環境をRenderに移す
- まずは、以下のレポジトリからソースをダウンロードする。
- これをもとにRenderへのデプロイ方法を紹介していく。
- ダウンロードファイルを開いて、その場で以下のコマンドを実行する(仮想環境作成)
- 本記事では、仮想環境名をmyenvにしている。
$ python3 -m venv 仮想環境名
$ source 仮想環境名/bin/activate
※以下の記事で、アプリの作成方法を説明している。
デプロイの流れ要点
- デプロイ前準備
- 既存ファイルの削除
- 既存ファイルの修正
- 新規ファイル作成(Renderデプロイ用)
- Djangoのカスタムコマンドを作る
- GitHubにコミットする
- RenderとGitHubを連携する
- Renderにデプロイ
Renderについて
RenderはHerokuと同様、PaaS型のクラウドプラットフォーム。
RDBMSも両者PostgreSQLになっている。
また、次の記事「【格安本番運用が可能に】Render.com のメリット・デメリットを Heroku と比較してみた」では、Herokuとの違いやデプロイ時の詳細設定について解説している。
個人的に、RenderはHerokuを意識している印象。
デプロイ前準備
既存ファイルの削除
以下の既存ファイルを削除する。
- Procfile(Heroku専用)
- runtime.txt(Heroku専用)
- report_project/settings_local.py
- README.md(pushに時間がかかってしまうので)
既存ファイルの修正
以下の既存ファイルを修正する。
- requirements.txt
- settings.py
- .env
requirements.txt
asgiref==3.5.2
dj-database-url==1.0.0
dj-static==0.0.6
Django==4.1.2
django-environ==0.9.0
django-model-utils==4.2.0
gunicorn==20.1.0
psycopg2-binary==2.9.5
python-decouple==3.6
python-dotenv==0.21.0
sqlparse==0.4.3
static3==0.7.0
whitenoise==6.2.0
ローカル環境で動作確認を行う場合は、以下のコマンドを実行して、仮想環境上(ここでは、myenv)にライブラリをインストールする。
※仮想環境の作成方法:仮想環境の作成とactivate
(myenv) $ pip install -r requirements.txt
settings.py
- 以下、4点の修正を加える
- ALLOWED_HOSTS
- DB設定
- staticファイル
- .envファイルからの環境変数読み込み
- Herokuの設定を解除
ALLOWED_HOSTS = ['127.0.0.1', 'daily-report.onrender.com']
デプロイ完了後のアプリのURLを指定する。つまり、daily-report.onrender.com
のところを独自のアプリケーションURLにする。
DATABASES = {
'default': {
'ENGINE':'django.db.backends.postgresql_psycopg2', # PostgreSQL使いますよ宣言
'NAME': 'appdb', # データベース名
'USER': 'postgres', # データベースに接続するDBユーザー名
'PASSWORD': 'password1', # データベースに接続する際のDBユーザのパスワード
'HOST': '', # 'localhost'
'PORT': '', # 5432
}
}
既存のものを以下に変更する。
import dj_database_url
# ~省略~
default_dburl = "sqlite:///" + str(BASE_DIR / "db.sqlite3")
DATABASES = {'default': dj_database_url.config(default=default_dburl)}
# postgresqlを設定する場合の書式は、postgresql://user_name:password@localhost:port/database_name(以下では、既存のものを書籍に当てはめている)
# DATABASES = {'default': dj_database_url.parse('postgresql://postgres:password1@localhost:5432/appdb')}
この設定にすると、データベースの設定は、「DATABASE_URL」という環境変数から読み込むようになります。これで、環境変数の指定を外部から変更できるようになります。
また、環境変数の指定がない場合には、Django の標準設定である、「SQLite」を利用します。
※Renderにデプロイすると自動的に、「DATABASE_URL」の値が設定される。
STATIC_URL = 'static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
# 以下を追加
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
STATIC_ROOT環境変数の下に追加
作成したnewsuperuserコマンド実行時に、settings.pyから値を取得するように定義したので、以下を追加する。
dotenv.load_dotenv() # .env ファイルを読み込む
SECRET_KEY = os.getenv('SECREST_KEY') # .env内の環境変数を取得
SUPERUSER_NAME = os.getenv('SUPERUSER_NAME')
SUPERUSER_EMAIL = os.getenv('SUPERUSER_EMAIL')
SUPERUSER_PASSWORD = os.getenv('SUPERUSER_PASSWORD')
末尾のHerokuに関する設定をコメントアウト、または削除する。
DEBUG = False # デプロイ時、Falseに修正
#DEBUG = True
#if not DEBUG:
#import django_heroku
#django_heroku.settings(locals())
新規ファイル作成(Renderデプロイ用)
- .env(環境変数設定用)
- build.sh
- render.yaml
- report/management/commands/newsuperuser.py(Renderの無料枠を使うため)
以下では、Render公式の「Getting Started with Django on Render」に記載されているものを参考にしていく。
.env
公に公開したくない環境変数をこのファイルに記述していく。
(.envは、.gitignoreに記述されているのでGitHub上で管理されない)
SUPERUSER_NAME = admin
SUPERUSER_EMAIL = admin@admin.com
SUPERUSER_PASSWORD = password
SECREST_KEY = ~~以下の説明をもとに値を設定する~~
- ここでは、今回のサービスのDjangoスーパーユーザーに関する設定と重要なSECREST_KEYの設定を記述している。
- これらの値は、settings.pyより取得される
- 末尾の
SECREST_KEY
の値の生成と設定方法は、「SECRET_KEY(環境変数)とは」を確認すること。
※SUPERUSER_EMAILは、#を先頭につけてコメントアウトしても問題ない
build.sh
デプロイ環境上で(ビルド時)実行するコマンドを記述する。
#!/usr/bin/env bash
# exit on error
set -o errexit
pip install -r requirements.txt
python manage.py collectstatic --no-input
python manage.py migrate
python manage.py newsuperuser
-
pip install -r requirements.txt
:デプロイ環境にライブラリをインストールするため。 -
python manage.py collectstatic --no-input
:--no-inputとしているのは、staticファイルをコレクト時にyesを入力することを省略するため。 -
python manage.py migrate
:モデルをDB上に反映させるため。 -
python manage.py newsuperuser
:後の**「Djangoのカスタムコマンドを作る」**の説明のところで作成するカスタムコマンド。
render.yaml
デプロイ環境の設定を記述する。
databases:
- name: mysite
databaseName: mysite
user: mysite
region: singapore
plan: free
services:
- type: web
name: mysite
env: python
region: singapore
plan: free
branch: main
healthCheckPath: /
buildCommand: "./build.sh"
startCommand: "gunicorn report_project.wsgi --log-file -"
envVars:
- key: DATABASE_URL
fromDatabase:
name: mysite
property: connectionString
- key: SECRET_KEY
generateValue: true
- key: WEB_CONCURRENCY
value: 4
autoDeploy: true
-
databases
:DBの設定- name:Render上で表示するDB名
- databaseName:DB名
- user:DBユーザー名
- region:DBサーバーの地域
- plan:DBのプラン
-
services
:サービスの設定- name:サービス名(URLになる)
- env:開発言語
- startCommand:APサーバー(gunicorn)を起動コマンド「gunicorn 自分のプロジェクト設定dir名.wsgi」
- envVars:環境変数の設定
envVars
の設定値以外は、小文字でないといけないかも
Djangoのカスタムコマンドを作る
Renderの無料枠では、 「Render側のシェル機能を使用することができない」 。
そのため、Djangoのスーパーユーザー(管理ユーザー)を事前に作成するためのコマンドを定義しておく必要がある。
以下では、「Djangoのカスタムコマンドを作成してコマンドラインから実行する」の記事を参考に、要点を説明していく。
※「build.sh」の説明のところで、末尾に記述しているpython manage.py newsuperuser
コマンドを作成していく
要点 | 説明 |
---|---|
① | python manage.py コマンド名を実行した時に処理する独自のコマンドを作成する。(今回はpython manage.py newsuperuserコマンド) |
② | ディレクトリは、アプリ/management/commands/直下にコマンド名となるpythonファイルを作成する(今回はreport/management/commands/newsuperuser.py) |
③ | BaseCommandクラスを継承してカスタムコマンドを作成する |
④ | コマンド実行後の処理は、handle()メソッド内に定義する |
from django.core.management.base import BaseCommand
from django.contrib.auth import get_user_model
from django.conf import settings
CustomUser = get_user_model()
class Command(BaseCommand):
def handle(self, *args, **options):
if not CustomUser.objects.filter(username=settings.SUPERUSER_NAME).exists():
CustomUser.objects.create_superuser(
username=settings.SUPERUSER_NAME,
email=settings.SUPERUSER_EMAIL,
password=settings.SUPERUSER_PASSWORD
)
print("スーパーユーザー作成に成功しました")
-
CustomUser = get_user_model()
:カスタムユーザーモデルを読み込む -
CustomUser.objects.create_superuser()
:カスタムユーザーモデルのマネージャーメソッドcreate_superuser()。引数に、スーパーユーザー名, スーパーユーザーemail, スーパーユーザーpasswordを指定する。
※厳密には、create_superuser()は、カスタムユーザーモデルが継承しているUserManagerクラスのメソッド(objects = UserManager())
参考記事:【Django】独自ユーザーモデルの作成(カスタムUserモデル:AbstractBaseUser)
GitHubにpushする
以下の記事を参考に、リポジトリに登録してpushする。
参考記事:レポジトリに登録してpush
参考記事:一旦pushしたい場合
RenderとGitHubを連携する
- Renderの公式ページにアクセスする。
Renderにデプロイ
- ナビゲーションバーの「Blueprints」をクリック
- 「New Blueprint Instance」をクリック
- GitHubのレポジトリ一覧が表示される
- デプロイしたいものの「Connect」をクリック
- 「Service Group Name」にrender.yamlのservicesのnameの値を入力する
- 「Apply」をクリック(デプロイ開始)
※これだけでは、Render側で環境変数を設定していないのでデプロイに失敗する。最後に以下の手順を踏む。
Render側(デプロイ環境)の環境変数の値を設定する
- Render公式ページのナビゲーションバー「Dashboard」をクリック
- 先ほどデプロイしたサービスが表示されていることがわかる
- デプロイしたサービス名(DBではなく)をクリック
- 「Environment」をクリック
-
PYTHON_VERSION
,SECREST_KEY
,SUPERUSER_NAME
,SUPERUSER_PASSWORD
を追加し、ローカルのpythonのバージョンと.envに記載した値を入力して「Save Changes」をクリック - 右上の「Manual Deploy」をクリックし、「Deploy latest commit」をクリック(再度デプロイ)
-
PYTHON_VEWSION
には3.7以上を指定する必要がある。(Django==4.1.2を使用するため。)今回は、3.10.7を指定している。 - あとは、
.env
で指定した値を設定する。
※Renderの無料枠を使用しているので、デプロイに時間がかかるが焦らずに待機する。
まとめ
以上が、DjangoをRenderへデプロイする方法でした。
ついつい最後のRender側の環境変数を設定し忘れてしまい、デプロイに失敗していましたが解決できてよかったです。
また、無料枠なので、デプロイに時間がかかりましたが問題なくサービスが稼働していることが確認できました。
わかりづらい点もあったかと思いますが、最後までお付き合いいただきありがとうございました。
Appendix
動作確認(ローカル)
ローカルで動作確認を行う場合は、以下のコマンドを実行するように。
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py runserver