CORESERVERでDjango 6を動かす【pyenv + MySQL】ロケットが表示されるまで

CORESERVER V2

はじめに

Django 6.0 は最新の Python と DB 環境を要求します。
CORESERVER V2の共用サーバーでは以下の問題に遭遇しました。

  • SQLite 3.31 未満エラー
  • mysqlclient バージョンエラー(1.4.6問題)
  • pyenv ビルド時の fork 制限
  • CGI で system 側 Python を拾う問題

本記事では「なぜ起きるのか」まで踏み込んで解説します。

前提(今回のゴールと方針)

  • Python は pyenv3.12.12を入れて使います。(Django6.0はPython3.12以上が必要)
  • 依存関係は venv に閉じ込めます。
  • 動作確認は runserver ではなく、最終的に CGIで実行しても venv が必ず使われる状態まで持っていきます。
  • Django 6.0はSQLiteの場合だと、Ver.3.31 以上を要求されるので、MySQLに切り替えることにします。
サーバー:CORESERVER V2(共用)
Python:3.12.12(pyenv)
Django:6.0.2
DB:MySQL
実行方式:CGI

最終的に下記URLでDjangoサイトにアクセスできるようにします。
https://django.tomomori.net/

https://django.tomomori.net/ は https://tomomori.net/ のサブドメインです。
CORESERVER V2でのサブドメインの作成は下記記事を参照してください。

CORESERVERでサブドメインを追加するには
はじめに(今回のゴール)このブログ(tomomori.net)は、CORESERVER V2プランで動作中ですが、djangoサイトを追加するため、django.tomomori.netというサブドメインを追加します。このサブドメインに対す...

pyenv をインストールまたはアップデートする

CORESERVER V2の共用サーバーにインストールされているPythonが古く、新しいバージョンのPythonを使う必要があります。そのために、pyenvで3.12をインストールしていきます。

インストールや設定の書き替えは、基本的にSSHでログインしたシェルで行うことになります。

pyenv が未インストールの場合:git clone して PATH を通す

CORESERVER環境で pyenv が入っていない場合は、git clone でユーザー領域に導入し、シェル設定に追記して反映します。ここでは bash を前提に説明します。

1) pyenv を git clone する(ユーザー領域)

まず、ホームディレクトリ配下に ~/.pyenv を作る形で clone します。

cd ~
git clone https://github.com/pyenv/pyenv.git ~/.pyenv

clone 後、ディレクトリができているか確認します。

ls -la ~/.pyenv

2) シェル設定に PATH と初期化を追記する(bash)

次に、pyenv が使えるように PATH初期化処理.bashrc(または .bash_profile)へ追記します。どちらに書くか迷う場合は、ログイン時に確実に読むよう .bashrc へ入れておくのが無難です。

nano ~/.bashrc

末尾に以下を追記します。

# ===== pyenv =====
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"

# pyenv init(bash用)
eval "$(pyenv init -)"

ポイント

  • PYENV_ROOT を固定し、$PYENV_ROOT/bin を PATH の先頭に入れます。
  • eval "$(pyenv init -)" がないと pyenv local などが期待通り動きません。

3) 反映する(source / 再ログイン)

追記したら、いったん反映します。

source ~/.bashrc

※ もしログインシェルが .bash_profile を読んでいて .bashrc を読まない構成の場合は、再ログインが必要になることがあります。
(不安なら、ログアウト→ログインし直すのが確実です)


4) pyenv が使えることを確認

pyenv コマンドが見えるか確認します。

pyenv --version

ここでバージョンが表示されれば、導入は完了です。

pyenv がインストール済みの場合:pyenvをアップデートする

pyenv を git で入れている場合は、基本は git pull です。

cd ~/.pyenv
git pull

pyenv-update プラグインを使っているなら、こちらでも更新できます。

pyenv update

pyenv でインストール可能なPythonバージョンの確認する

pyenv install -l

下記は抜粋です。

  3.12.0
  3.12-dev
  3.12.1
  3.12.2
  3.12.3
  3.12.4
  3.12.5
  3.12.6
  3.12.7
  3.12.8
  3.12.9
  3.12.10
  3.12.11
  3.12.12
  3.13.0
  3.13.0t
  3.13-dev
  3.13t-dev
  3.13.1
  3.13.1t
  3.13.2
  3.13.2t
  3.13.3
  3.13.3t
  3.13.4
  3.13.4t
  3.13.5
  3.13.5t
  3.13.6
  3.13.6t
  3.13.7
  3.13.7t
  3.13.8
  3.13.8t
  3.13.9
  3.13.9t
  3.13.10
  3.13.10t
  3.13.11
  3.13.12
  3.13.12t
  3.14.0
  3.14.0t
  3.14-dev
  3.14t-dev
  3.14.1
  3.14.1t
  3.14.2
  3.14.3
  3.14.3t
  3.15.0a6
  3.15.0a6t
  3.15-dev
  3.15t-dev

一覧が長い場合は絞ります。

pyenv install -l | grep 3.12

Python 3.12.12 を入れて pyenv local 3.12.12 を実行する

pyenv install 3.12.12

しかし、ここで下記エラーになってしまいました。

make: fork: Resource temporarily unavailable

なぜ fork エラーが起きるのか?

共用サーバーではプロセス数制限(LVE制限)がかかっているようです。

Pythonビルドは内部で大量のプロセスを生成します。
そのため、並列ビルド(-j オプション)により制限に引っかかってしまったようです。


解決方法(並列を無効化)

下記のようにTMPDIRを設定するとともに、 MAKE_OPTS 環境変数に -j1 を設定し、並列処理数を1つにしました。

TMPDIR=$HOME/.tmp/pyenv \
MAKE_OPTS="-j1" \
pyenv install 3.12.12

ポイント:

  • -j1 にして並列無効化
  • TMPDIR を noexec でない場所に変更

Djangoの作業ディレクトリを作成して local に 3.12.12 を設定

Python3.12が無事にインストールできたら、次にDjangoサイト用のディレクトリを作成して、Python3.12を使うように設定します。ここでは~/apps/djangoに対してlocalとしましたが、globalに設定する事もできます。

mkdir -p ~/apps/django
cd ~/apps/django
pyenv local 3.12.12
python -V

ここで Python 3.12.12 と出ればOKです。

venv を作って activate する

cd ~/apps/django
python -m venv venv
source venv/bin/activate
python -V

以降、プロンプトに (venv) が付いていればOKです。

pip を最新化する(事故防止)

古いpipだとビルドや依存解決で余計な事故が増えます。ここでpipをアップデートしておきます。

python -m pip install -U pip
pip -V

Django 6.0 をインストールする

いよいよ、Django 6.0 をインストールします。下記をもう一度確認してから、インストールしてください。

  • プロンプトに (venv) が付いている事
  • 現在のディレクトリが 「~/apps/django」であること
pip install "Django>=6.0,<6.1"
python -m django --version

Djangoプロジェクトを作成する

django-admin startproject config .

ここはハマりポイントです。最後の「.」が重要です。
最後に . を付けることで、カレント直下に manage.pyconfig/ が作られます。

作成後の構成(こうなればOK)

~/apps/django/
├── config/
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   ├── asgi.py
│   └── wsgi.py
├── manage.py
└── venv/

migrateしてDBを作成したあと、スーパーユーザを作成する

python manage.py migrate

SQLite エラー

しかし、ここで下記エラーが発生してしまいました。

django.db.utils.NotSupportedError:
SQLite 3.31 or later is required (found 3.26.0).

なぜ起きた?

Django 6 は SQLite 3.31+ が必須のようです。
しかし、CORESERVERの共用サーバーの SQLite は古いのが原因でした。Pythonを新しくしても、リンクされているSQLiteはsystem側のものを参照しているようでした。
下記コマンドでバージョンを確認できます。

python -c "import sqlite3; print(sqlite3.sqlite_version)"
3.26.0

解決策

SQLite を使わず、MySQL に切り替えることにします。
理由:

  • 共用サーバーでは MySQL が安定
  • SQLite を自前ビルドするのは難易度高

CORESERVER V2でMySQLデータベースを新規作成する方法

下記にマニュアルがありますので、これを参照して新しいDBを作成してください。
作成完了後に表示される情報は、あとでsettings.pyに埋め込んでいきます。

データベースの新規作成 | マニュアル | サポート | レンタルサーバー CORESERVER(コアサーバー)
レンタルサーバー「コアサーバー」のサポートページです。初心者でも気軽に使えるようサポートにも力を入れています。ライブチャットやお問い合わせフォームも存分にご活用ください。

Djangoの設定ファイル(settings.py)を編集する

settings.pyをエディタで開きます。

nano ~/apps/django/config/settings.py

DB設定部分を下記のように書き替えて保存します。

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": "表示された DB_Name",
        "USER": "表示された DB_User",
        "PASSWORD": "表示された Password",
        "HOST": "localhost",
        "PORT": "3306",
        "OPTIONS": {
            "charset": "utf8mb4",
        },
    }
}

ついでに、日本語と静的ファイルの設定部分および「ALLOWED_HOSTS」も書き替えて保存します。(ALLOWED_HOSTSにはご自身のサブドメインを入力してください。)

BASE_DIR = Path(__file__).resolve().parent.parent
・・・
ALLOWED_HOSTS = ["django.tomomori.net"]
・・・
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
USE_I18N = True
USE_TZ = True
・・・
STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / "staticfiles"

最新の mysqlclient をインストールする

Django 6.0 は Python 3.12 が前提で、オプション依存もPython 3.12対応が必要です。
Django 6.0 のリリースノートでは、mysqlclient 2.2.1 が Python 3.12 対応を満たす最初の版として挙げられています。

下記コマンドで最新のmysqlclient を仮想環境にインストールします。(プロンプトに (venv) が付いている事を確認してください。)

pip install --upgrade mysqlclient

インストールができたら、下記コマンドでバージョンを確認しておきます。私の環境では2.2.8がインストールされました。

pip list | grep mysql

再度、migrateを実行しスーパーユーザを作成する

MySQL用にsettings.pyを書き替えて保存したあと、再度、マイグレートを実行します。

python manage.py migrate

続いて、スーパーユーザを作成します。

python manage.py createsuperuser

任意のユーザー名、メールアドレス、パスワードを入力して登録を完了させてください。
ここで登録したユーザを使ってDjango管理サイトにログインする事ができます。

collectstatic を実行して必要な静的ファイルを収集する

ここまでで python manage.py migrate が成功し、データベースの準備は完了しました。しかし、CGI経由で公開する前に必ずやっておくべき作業があります。

それが collectstatic です。

前節でsettings.pyにSTATIC_URLSTATIC_ROOTを設定済みですので、 プロンプトに (venv) が付いている事を再度確認してから下記コマンドを実行します。

cd ~/apps/django
python manage.py collectstatic

成功すると、staticfiles/ ディレクトリが作成され、中に大量のCSSやJSが生成されます。

CGI経由でDjangoサイトにアクセスできるようにする

CORESERVERは一般的なレンタルサーバー(共有サーバー)であるため、runserverコマンドをバックグラウンドで動かし続けることはできません。

Python実行環境とDjangoのWSGIアプリケーションを仲介するCGIスクリプトを作成します。

先人が作成したCGIスクリプトが下記で見つかったのですが、残念ながら私の環境では正しく動作しませんでした。
https://raw.githubusercontent.com/chibiegg/django-cgi/master/django-python2.cgi

そこで今回は、わたしの環境に合わせてdjango.cgiを作成しました。[ユーザ名]のところはご自身のユーザ名に書き替えてください。必要最低限の短いコードになりました。

#!/home/[ユーザ名]/apps/django/venv/bin/python
import os
import sys
from wsgiref.handlers import CGIHandler

PROJECT_DIR = "/home/[ユーザ名]/apps/django"
VENV_SITE = "/home/[ユーザ名]/apps/django/venv/lib/python3.12/site-packages"

# ★ ここが重要:venvのsite-packagesを最優先にする
sys.path.insert(0, VENV_SITE)
sys.path.insert(0, PROJECT_DIR)

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

CGIHandler().run(application)

これを、django.cgiというファイル名で保存します。

/home/[ユーザ名]/domains/django.tomomori.net/public_html/cgi-bin/django.cgi

chmodで実行権限を付けます。(私の環境では705でOKでした。)

chmod 705 ~/domains/django.tomomori.net/public_html/cgi-bin/django.cgi

Djangoサイトにアクセスする(ロケットを表示する)

ここまでできれば、ブラウザでDjangoサイトにアクセスできるはずです。
下記URLをブラウザで開いてみてください。(ドメイン名はご自身のものに変更してください。)

https://django.tomomori.net/cgi-bin/django.cgi

上記のようにロケットが表示されれば、ひとまず成功です。

あとは、cgi-bin/django.cgiを隠して、 https://django.tomomori.net/ だけでアクセスできるようにしていきたいと思います。これについては、下記の別記事を参照してください。

Django管理画面にアクセスする

下記にアクセスするとDjango管理サイトへのログイン画面が表示されます。

https://django.tomomori.net/cgi-bin/django.cgi/admin/

しかし、CSSが適用されず、画面が崩れてしまっていると思います。

これは CGI 環境では静的ファイル(admin の CSS 等)を Django が配信しないために起きてしまいます。対処として collectstatic と static 公開設定が必要です。

これに対応する方法は別記事にしましたので、下記を参考に対応してください。

表示されたログイン画面で、ユーザ名、パスワードを入力すると管理画面にログインできます。(ユーザ名、パスワードは、先ほどcreatesuperuserで作成したものです。)

まとめ

ここまで、CORESERVER V2 で Django 6.0 を動作させる方法を見てきましたが、ざっくりまとめると、下記の手順になります。

  • pyenv更新 → 3.12.12 を入れて local 指定
  • venv作成 → pip更新 → Django 6.0 インストール
  • startproject config .最後の . が重要
  • migrate で止まったら
    • SQLiteのバージョン確認(Django 6.0 は SQLite 3.31+
    • 共有サーバーなら MySQLに切り替えるのが現実的
  • MySQL利用なら mysqlclient 1.4.6系を避ける(Django 6.0では mysqlclient 2.2.1 がPython 3.12対応の目安)
  • CGI運用は shebang を venv のpython絶対パス固定が肝

結果、動作はしましたが、CGI方式は実行速度が遅いなど、他に比べて不利なことが多いのは確かです。
この記事が、どなたかのお役に立てば幸いです。

コメント

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