【Django】Heroku無料枠がなくなるのでRenderを使ってみた。

この記事は約16分で読めます。
広告

Herokuが2022/11/末から有料になるため代わりになるRenderを使ってみました。どうにかデプロイできたので、その様子をご紹介します。Herokuで動いていたものを動かすことができました。HerokuやRailwayとは違ってアプリによってはアプリ自体の修正が必要になりました。まずはAnacondaで作ったDjangoアプリをRenderにデプロイしたときにハマったことと解決策のご紹介。それとHerokuで動いていたものをRenderにデプロイしたときにハマった内容のご紹介です。
Renderの登録方法などは省略しています。
使用した環境Windows11、Anaconda、Git、VSCode

2023/02/17以下のメールが来ました。90日たったのでデータベースにアクセスできなくなりました。
Your free Render PostgreSQL database, django_render_db, will be suspended on 2023-02-17. The database will become inaccessible unless you upgrade to a paid plan.
PostgreSQLではなくsqlite3使っているから大丈夫だと思っていたのですが、データが保存されなくなっていたりエラーが出たりしています。1番下にPostgress→SQLite3の記事追記しました。

Renderにデプロイしたアプリ
Django+Vuetify掲示板 (表示するまで数分かかることがあります)
データ入力グラフ描画(表示するまで数分かかることがあります)

私の他のDjangoの記事でも成果物はRailwayとRenderにそれぞれデプロイしています。
同じくHerokuの代替Railwayについてはこちらの記事。

AnacondaでDjangoアプリを作る場合、エディタはVSCodeを使ったほうがいいです。というのはRender.comを使うときに作るbuild.shファイルの改行コードがLFでなければエラーになりVSCodeだとこの変換が簡単にできます。(Spyderを使ってもできると思いますが、やり方は調べてません。)

広告

Renderにデプロイ

Renderにデプロイする方法はこちらを参考にしました。
参考サイトDjangoをRenderにデプロイする方法
Anacondaをインストールしていない環境では、この通りいけると思います。
私はデプロイの前の仮想環境でつまづきました。というのもAnacondaをインストールしているとうまくいきません。
Anacondaをアンインストールしたくなかったので上述のAnaconda仮想環境で、参考サイトのアプリを作りデプロイしました。参考サイトと違う部分を記述します。

Anacondaの場合、上の「Environments」→「該当の仮想環境」→「Open Terminal」でこのターミナルを使っていきます。
この状態で参考サイトの「仮想環境の作成」と「仮想環境の実行」は不要になります。

python3 manage~ではエラーになるのでpython manageでやりました。
例えばpython manage.py startapp app

RenderのNew Blueprint Instance ボタンをクリックしたときレポジトリがないときはConfigure accountをクリックRepository accessがOnly select repositoriesになっているためこうなります。select  repositoriesでレポジトリが選べるようになります。

デプロイでCreate web service django_render
(git branch not found: "main" in https://api.github.com/repos/miyamiko/mysite/commits/main)とエラーが出たので
render.yamlのservices:の branch: main →master変更でOKでした。(masterだったのは私がGitHubにプッシュするときgit push origin masterでプッシュしたからです。)
目次へ

Heroku、Railwayでうまくいっていたのにエラーが出たこと

Heroku、Railwayで動いていたアプリをRenderにデプロイするときにはまったことです。

/usr/bin/env: ‘bash\r’: No such file or directoryが出る

/usr/bin/env: ‘bash\r’: No such file or directoryが出たときの対処法を参考に
VSCodeでbuild.shを開いて改行をlfに変えてok
VSCodeで*.shでファイルを新規作成したときは自動的に改行コードがLFになっているので何もする必要はありません。

Not Found: /

ルートに何かを表示する処理がないとデプロイ失敗になります。
なので処理を追加、具体的にはプロジェクトのほうのurls.pyにルートの表示処理を追加する。

urlpatterns = [
    path('',~)←これがないとデプロイ失敗になる。

app.models.モデル名.DoesNotExist: モデル名matching query does not exist.

デプロイ完了後いきなりアプリが立ち上がりデータオブジェクトがない処理だとデプロイ失敗になってしまう。Herokuでは起動する前にPythonシェル起動やadminを起動してデータオブジェクトを作成できたので、デプロイ失敗にはならなかった。
get_or_create()を使うと最初の1回だけオブジェクトを作成する処理を作れる。
参考【django】モデルの get_or_create()の使い方

sqlite3を使う場合だったらローカルでデータ入力しておけばデプロイしても、そのまま使える。ただデータベースのデータはdb.sqlite3にはいっている。なので.gitignoreでdb.sqlite3を書いてるとGitHubにdb.sqlite3がプッシュされないので消しましょう。

relation “モデル名” does not exist

adminでモデルをクリックしたときやapiでモデルにアクセスしようとすると出る。migrateがうまくいってないようです。
具体例
relation “article_vtfyarticle” does not exist(articleはアプリ名_vtfyarticleはモデル名)

解決策

build.shの
python manage.py migrate
→
python manage.py migrate --fake article zero
python manage.py migrate article
articleはアプリ名
デプロイ時のログでarticle.0001_initialが適用されているのが確認できました。
Jan 5 07:16:26 AM    Apply all migrations: article
Jan 5 07:16:26 AM  Running migrations:
Jan 5 07:16:26 AM    Applying article.0001_initial... OK

参考
postgresql – django.db.utils.ProgrammingError: relation “bot_trade” does not exist – Stack Overflow

djangorestframework==3.10.0だとエラー

何かimportできないエラーが出た。(具体的には忘れました)
Djangoのバージョンとの関係だと思いますがrequirements.txtでバージョン指定しないでdjangorestframeworkとすればデプロイは通る。
また参考サイトではrequirements.txtでdjango==4.1.2にしてRenderのEnviroment環境変数設定でPYTHON_VERSION 3.8.10に変更しています。最初からrequirements.txtで3.8.10にしてみましたが、これではヴァージョンがないというエラーになりました。なので参考サイトの手順でやらないとダメでした。

細かいところまでチェックされダメだとデプロイ失敗になる。

HerokuやRailwayではチェックされないところまでチェックされます。やっかいなのはデプロイ失敗として扱われて先に進めないところです。

具体的に出たエラーは
The JS file 'app_cal/js/chunk-vendors.17cbe1d3.js' references a file which could not be found:
Nov 23 05:51:19 PM    app_cal/js/chunk-vendors.17cbe1d3.js.map
mapファイル(デバックで使う)がないというエラー

jsファイルの以下の該当部分を削除したらOKでした。
//# sourceMappingURL=app.e34c0f45.js.map

プロジェクトが違っても同じモデル名やアプリ名だと動作がおかしい

HerokuやRailwayでは問題なかったのに別プロジェクトの同じモデル名やアプリ名だと干渉してしまう。アプリを作り直した。

5秒ごとに”GET / HTTP/1.1″ 200 10831 “-” “kube-probe//”が発生する

プログラムによっては問題になるので注意です。Renderが5秒おきにアクセスしてヘルスチェック(ちゃんと動いてるか)してるようです。私はアクセスカウンターのアプリで、これによりうまくカウントできなくなりました。
views.pyにprint(request.headers)をおいて、どんなrequestが来てるか見ようとしましたが何も入ってません。またチェックしてるのはルートのアプリだけのようで他のところのアプリのアクセスカウンタでは不具合はおきません。なのでurls.pyでルートから変えてみたけどダメでした。最初にルートのアプリに設定したらそれについてくるのか?個人的対策として、ヘルスチェックを受けたくないアプリは最初のデプロイでルートにおかないようにしようと思います。
HerokuやRailwayでは起きていなかったのに。うまくいかなくなったアプリの記事

502 Bad Gateway

logでは最初デプロイ成功になっているがGET / HTTP/1.1″ 400が連発して最終的にはdeploy failedになる。
settings.py
私の最初の設定ALLOWED_HOSTS = [‘.onrender.com’,’localhost-abc-1.paiza-user-free.cloud’, ‘.herokuapp.com’]をALLOWED_HOSTS = [‘*’]にしたらとりあえずデプロイは成功してアプリも表示する。すべてを表す*ではちょっと心配なので[‘.onrender.com’]を試したけどダメ。サブドメインつきの[‘vtfy2article.onrender.com’]でもダメでした。他のアプリは問題なかったのになぜ?
Delete Web Serviceしてやり直したり、デプロイするときハイライトされてないほうのボタンでやったり、
いろいろやっているうちにログに以下が出てきたので ‘127.0.0.1’ 追加しました。
Invalid HTTP_HOST header: ‘127.0.0.1:10000’. You may need to add ‘127.0.0.1’ to ALLOWED_HOSTS.
最終的にはこれでOKになりました。
ALLOWED_HOSTS = [‘vtfy2article2.onrender.com’,’127.0.0.1′]
‘127.0.0.1’はlocalhostと同じ。ループバックアドレスといって自分自身をさすIPみたいです。そういえばローカルでやるときは、ここにアクセスしますね。

Postgressに変更する方法

SQLiteからPostgressへ変更する方法。簡単にできるので本当にPostgressで動いているのか確認の仕方がわかりませんがエラーにはなりませんでした。

settings.pyで以下のように変更する
import dj_database_url
# DATABASES = {
    # "default": config("DATABASE_URL", default=default_dburl, cast=dburl),
# }
DATABASES = {"default": dj_database_url.config()}

参考
https://render.com/docs/deploy-django
https://django.baby/deploy-django-to-render-com/
https://github.com/yeconnect/deploy_django_on_render/blob/main/config/settings.py

目次へ

Postgress→SQLite3

SQLite3で動いているとばかり思っていたらPostgressで動いていたようです。3カ月でPostgressの期限切れでアプリが動かなくなりました。
まだ調査途中で動きはおかしいですが、PostgressからSQLite3に変更してデプロイだけは成功したので紹介します。ただし、データの読み書きはできますが再度立ち上げた時データが保存されていない。db.sqlite3が更新保存されていないようです。これを参考に、ご自分で詰めていってください。

git clone https://github.com/****/****.git
cd ****
code .
render.yamlの以下削除
databases:
  - name: django_render_db
    region: singapore
    plan: free
    databaseName: django_render_db
    user: django_user

以下は恐らくPostgressの設定がされていればPostgressを使ってされていないときは、SQLite3を使うというコードだったと思われます。これをSQLite3を使うと明示しました。(Djangoに最初から入っているコードに戻した。)

settings.pyでDATABASE変更
# DATABASES = {
#     "default": config("DATABASE_URL", default=default_dburl, cast=dburl),
# }
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
git status
git add .
git commit -m "sqlite3に変更"
git push origin master

RenderのDashboadで該当するアプリを選択Manual Deploy→Deploy latest commit

SQlite3で最初から動かす場合

今、私が運用しているこの方法だとローカルで作ったdb.sqlite3のまま更新保存されません。ただシンプルに運用できるので紹介しておきます。

ローカルで以下をやっておきます。
python manage.py makemigrations (migrationフォルダができないときは最後にアプリ名入れるとmigrationフォルダできる)
python manage.py migrate
migrateやpython manage.py createsuperuser
アプリを動かしてデータベース(db.sqlite3)にデータを入れておく。

build.sh
set -o errexit

pip install -r requirements.txt

python manage.py collectstatic --no-input

render.yamlのstartCommand:はgunicorn (wsgi.pyのあるディレクトリ).wsgi:applicationの形です。またRenderの各アプリのsettingsのStart Commandにも同じものを入力します。

render.yaml
services:
  - type: web
    name: アプリ名 例vchartren2
    env: python
    region: singapore
    buildCommand: './build.sh'
    startCommand: 'gunicorn project_vchart2.wsgi:application'
    plan: free
    branch: main
    healthCheckPath: /
    envVars:
      - key: DATABASE_URL
        fromDatabase:
          name: django_render_db
          property: connectionString
      - key: SECRET_KEY
        generateValue: true
      - key: WEB_CONCURRENCY
        value: 4
    autoDeploy: true

Superuserコマンドは使用せず、ローカルで作っておきます。なのでsettings.pyもSuperuser関連やデータベースのPosgress関連の処理はなくしました。

settings.py
from pathlib import Path
import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
# BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
BASE_DIR = Path(__file__).resolve().parent.parent
略
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
略
# STATIC_URL = '/static/'
STATIC_URL = "static/"
STATIC_ROOT = str(BASE_DIR / "staticfiles")
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

GitHubにデプロイしたらブループリントではなくDashboadからNew→WebService→WebConfigure accountをクリック(Repository accessがOnly select repositoriesになっているためこの作業が必要になる。)select  repositoriesでレポジトリが選べるようになります。選んでConect。環境変数設定はPYTHON_VERSION 3.8.10のみでSuperuserはやらない。

まとめ

気づいたことがあったら随時更新します。

  • HerokuやRailwayではハマらなかった内容でハマった。
  • アプリが異なっていても同じデータベースのモデル名を使っていると干渉してしまいアプリを作り直した。
  • 5秒おきに実行されるへルスチェック(ちゃんと動いてるか)も動作に影響がある。
  • スリープ状態から立ち上がるまで数分かかるときがある
  • BlueprintsのstatusがSync failed(原因未調査)でもとりあえず動く。今はBlueprintsを削除して使っている。
  • ローカルでうまくいっていたページネーションがうまくいかない。(原因未調査)
  • 3か月後Postgressが使えなくなる。SQLite3に変えるがデータが残ってない。(原因調査中だが、このまま使うかも)

この記事を書いたイチゲを応援する
Vプリカでのお支払いがおすすめです。
MENTAやってます(ichige)
目次へ

コメント

タイトルとURLをコピーしました