poetryなしでDjangoをRender.comへデプロイする【Herokuの代替クラウド、アカウント作成から解説】
- 作成日時:
- 最終更新日時:
- Categories: インフラ
- Tags: Django render.com デプロイ クラウド
2022年11月28日、Herokuのサービスが完全無料で利用できなくなった。
そこで、代替のクラウドクラウドサービスとして最有力候補のRender.comを使用する。
90日間しかDBは持たないとは言え、就活用のポートフォリオとしてウェブアプリを公開するには十分かと思われる。
本記事では、DjangoをRender.comへデプロイする方法を解説する。
Render.comの基本情報
箇条書きで並べる。最近知ったので、一部間違いがあるかも。
- ウェブサーバーとDBサーバー(PostgreSQL)が無料で利用できる
- PostgreSQLは90日間無料、それ以降は要課金
- サーバーサイド三大フレームワークに対応(Rails、Laravel、Django)
- 静的サイトジェネレーターにも対応(HUGO、Gatsby)で完全無料
- dockerにも対応
- 有料だが、cron(タスクスケジューラー)が用意されている
- アカウントはGitHubのアカウントから簡単に作ることができる(パスワード不要)
- デプロイはHerokuとは違い、GitHubからリポジトリを登録してデプロイする
Render.comのアカウント作成
下記URLへアクセスする。
https://dashboard.render.com/register
GitHubをクリックすると、お手元のGitHubアカウントを使ってアカウント作成ができる。持っていない場合はグーグルアカウントか、EmailとPasswordを入力
アカウントアクティベート用のメールが送信されるので、URLをクリックする。
アカウント作成後、ダッシュボードが表示される。
Render.comにて、リポジトリを追加する
ウェブサービスを作る。ダッシュボードから、Web Service
をクリックする。
https://dashboard.render.com/select-repo?type=web
右の欄から、GitHubの連携が指定できるので、下記画面に移動して、
送信する。
そうすると、このように、GitHubのリポジトリが選べるようになる。
Djangoをデプロイする
流れ
- ダッシュボードからウェブサービスとPostgreSQLを作る
- 環境変数の設定
- Djangoのsettings.pyの編集
- 必要なライブラリを仮想環境にinstallしてrequirements.txtを作る
- GitHubにプッシュする
ダッシュボードからウェブサービスとPostgreSQLを作る
まずウェブサービスを作る。青色の New + のボタンをクリック Web Service を選んで リポジトリの選択画面に移る。下記URLクリックでもOK。
https://dashboard.render.com/select-repo?type=web
ここでこれからプッシュする予定のリポジトリをConnectする
Name、Runtime、Build Command、Start Command、をそれぞれ指定しておく
インスタンスタイプは無料でOK。 インスタンスを作る
続いて、PostgreSQLを作る。New + のPostgreSQL もしくは下記リンクをクリックする。
https://dashboard.render.com/new/database
Name、Database、Userをそれぞれ指定する。
無料でインスタンスを作る。DBが作られるまでに3分ぐらいかかるので注意。
下記のDBの情報は後の環境変数で使うので、控えておく。
環境変数の設定
必要な環境変数は下記
DATABASE_URL : 前項のInternal Database URLをコピーして貼り付け
PYTHON_VERSION : 開発環境で使用しているPythonのバージョンと同じものを指定する。(python3 --version)
RENDER_EXTERNAL_HOSTNAME : ALLOWED_HOSTSに入れるので、ウェブサービスのドメイン名を書く(今回の場合 startup-bbs2.onrender.com )
SECRET_KEY : settings.pyのSECRET_KEYをリジェネレートして当てる
WEB_CONCURRENCY : 4 を指定(どこで使うのか不明、未検証)
Djangoのsettings.pyの編集
Herokuのときと同様、Renderデプロイ時に一部の設定を反映させる。
ただし、前項で設定した環境変数を読み取っている。(GitHubにプッシュしてデプロイする仕様上、Renderの環境変数に機密情報は入れておかないと危険。)
""
Django settings for config project.
Generated by 'django-admin startproject' using Django 3.2.10.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/
"""
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-9w@vg!_m8nn%htbj8)^_kjdk2cxb$jx!!g$35)z%el&r&y1%cj'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
# ここで環境変数にRENDERがあれば、DEBUG = Falseとなる。
import os
DEBUG = 'RENDER' not in os.environ
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
"bbs.apps.BbsConfig",
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'config.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [ BASE_DIR / "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',
],
},
},
]
WSGI_APPLICATION = 'config.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
STATIC_URL = '/static/'
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# Renderデプロイ時に反映させる設定
if not DEBUG:
# SECRET_KEYは環境変数から取り出す
SECRET_KEY = os.environ.get('SECRET_KEY', default='your secret key')
# ALLOWED_HOSTS も環境変数から取り出す。
RENDER_EXTERNAL_HOSTNAME = os.environ.get('RENDER_EXTERNAL_HOSTNAME')
if RENDER_EXTERNAL_HOSTNAME:
ALLOWED_HOSTS.append(RENDER_EXTERNAL_HOSTNAME)
# DBの設定
import dj_database_url
DATABASES = {
'default': dj_database_url.parse(os.environ.get('DATABASE_URL'), conn_max_age=600),
}
# whitenoiseの読み込み
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
if not DEBUG:
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
必要なライブラリを仮想環境にinstallしてrequirements.txtを作る
virtualenv venv
source ./venv/bin/activate
仮想環境に入る
pip install django dj-database-url gunicorn whitenoise psycopg2
pip freeze > requirements.txt
これでrequirements.txtを作る
後は、ビルド用のシェルスクリプトを書く
以下をbuild.shとしてDjangoのプロジェクトディレクトリ直下に配置。
#!/usr/bin/env bash
pip install -r requirements.txt
python manage.py collectstatic --no-input
python manage.py migrate
GitHubにプッシュする
以上の設定を踏まえた上で、GitHubへプッシュする。
もし、問題がなければ、このようにEventsのログにデプロイ成功のログが表示される。
デプロイするとこうなる。
Herokuと同様にドメインが与えられるので、就活や転職のポートフォリオとしては十分だと思う。
ただし90日経ったらDBは使えなくなるので、その都度新しいDBを作ると良いだろう。
注意点
- Herokuではできていたコマンドがrenderでは実行できない
- 挙動が遅い
- データベースは3ヶ月で消える
- GitHubにプッシュするので、機密情報のプッシュに注意
- ストレージはAWSのS3を使うしかないっぽい?
注意点はざっとこの辺りだろうか?
Herokuの場合は heroku run python3 manage.py createsuperuser
で管理ユーザーを作れていたが、render.comの場合シェルの利用は有料らしい。
管理ユーザーのデータを含んだ.jsonファイルをloaddataで読み込ませる方法も有るが、安全ではないと思う。
それからGitHubにプッシュするのでSendgridやStripeのAPIなどの機密情報のプッシュには注意。そういったものは環境変数を設定しておく。
ストレージはAWSのS3を使うしかないっぽい?
結論
poetryの使用は必須ではないということがわかった。
Pythonのバージョンを指定すること、requirements.txtに必要なライブラリを書いておくこと。これさえできればpoetryなしでもデプロイはできる。
GitHubを使うので、サーバーサイドのソースコードは丸見えだが、ポートフォリオとして使うには十分だと思う。
画像などのファイルアップロード機能を有する場合は、S3などのストレージを使うと良いだろう。
DBは90日間しか使えないとはいえ、DBを消して再度作り直すことで半永久的に使えるっぽい。データは消えてもいいからポートフォリオとしていつまでも機能させたい場合にはいいだろう。
何なら、初期データをloaddataコマンドでインプットさせておけば良いと思う。