自動化無しに生活無し

WEBとかAIとかLinux関係をひたすら書く備忘録系ブログ

poetryなしでDjangoをRender.comへデプロイする【Herokuの代替クラウド、アカウント作成から解説】

thumbnail

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をデプロイする

流れ

  1. ダッシュボードからウェブサービスとPostgreSQLを作る
  2. 環境変数の設定
  3. Djangoのsettings.pyの編集
  4. 必要なライブラリを仮想環境にinstallしてrequirements.txtを作る
  5. 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コマンドでインプットさせておけば良いと思う。

ソースコード

https://github.com/seiya0723/render2

スポンサーリンク

シェアボタン

Twitter LINEで送る Facebook はてなブログ