06-Django

Django デプロイ(まとめ)

Django デプロイ作業

この記事では「Djangoのデプロイ作業」の基本的な流れを「Virtual Box」を利用して行います。作業内容は以下の通りです。

ローカル側(開発環境側)での作業

  1. 「settings.py」を編集する
  2. 利用しているパッケージを「requirements.txt」に出力する
  3. Githubへプロジェクトをpushする

サーバー側(本番環境側)での作業

  1. Virtual BoxにRocky Linux を準備する
  2. DBMS(この記事ではPostgreSQL)のインストールと設定
  3. gitのインストールと設定
  4. Githubからプロジェクトをクローンする
  5. python仮想環境の準備
  6. gunicornのインストールと設定
  7. Webサーバー(この記事ではnginx)のインストールと設定

ローカル側(開発環境側)での作業

ローカル側では次の作業を行います。

  1. 「settings.py」の編集
  2. 「requirements.txt」の出力
  3. Githubへのプロジェクトのpush

settings.pyの編集

プロジェクトフォルの中にあるsettings.pyですが、デプロイ前には次の処理を行っておきます。

  1. プロジェクトフォルダ内に新しく「settings」フォルダを準備する。
  2. 「開発環境用のsettings.py」を準備する。→この記事では「settings_develop.py」
  3. 「本番環境用のsettings.py」を準備する。→この記事では「settings_product.py」
  4. 「共通で利用できるsettings.py」を準備する→この記事では「base.py」
  5. 「settings」フォルダに「__init__.py」を作成する。

まずは、「settings.py」のあるディレクトリに「settings」ディレクトリを準備します。その後、準備した「settings」ディレクトリに「settings.py」を移動して名前を「base.py」に変更します。

本番環境は「production environment」と呼ぶので、「settings_product.py」という名前が気になる方は「settings_production.py」としてください。

続けて、「settings_develop.py」、「settings_product.py」、「__init__.py」の3つのファイルを「settings」フォルダ内に新規で準備します。

(__pycache__ディレクトリは作業中に自動的に生成されるものなので開発者が作成したりはしません。)

(再確認)もとの「settings.py」の名前を変更して「settings」フォルダに移動したものが「base.py」です。

「settings_develop.py」と「settings_product.py」には開発環境と本番環境で設定が変更される部分をそれぞれ「base.py」から抜き出しておきます。

「__init__.py」ファイルには次のように入力します。

# 本番環境
from .settings_product import *

try:
    # 開発環境
    from .settings_develop import *
except:
    pass

base.py(もとのsettings.py)から開発環境用の「settings_develop.py」と本番環境用の「settings_product.py」へ「SECRET_KEY」「DEBUG」「ALLOWED_HOSTS」「DATABASES」を切り取り、貼り付けます。この記事では少し編集を加えたため若干の違いがありますが、本来なら、どちらにも同じ状態が作成されています。

from .base import *

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-***この部分はデフォルトの鍵が入っています。***'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

#この部分には開発環境でのIPアドレスを入れています。
ALLOWED_HOSTS = ["127.0.0.1", "192.168.2.139"]

# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

もう一つのファイル「settings_product.py」を次のように編集します。

from .base import *

# SECURITY WARNING: keep the secret key used in production secret!
# 何も入力しません。
SECRET_KEY = ''
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False

#この部分には本番環境でのIPアドレスを入れます。現在は「*」としています。
ALLOWED_HOSTS = [" * "]

# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

「base.py」の中にある「BASE_DIR」の箇所を次のように編集します。

(編集前)BASE_DIR = Path(__file__).resolve().parent.parent

(編集後)BASE_DIR = Path(__file__).resolve().parent.parent.parent

これは「main.py」のある階層に対して「base.py(もとのsettings.py)」の位置がディレクトリをひとつ増やして階層が深くなったためです。

以上で「settings.py」の編集は終了です。

ここまで編集が終わったら「python manage.py runserver」コマンドで実行ができるかを確認します。(開発環境としての実行です。)もし、実行ができない場合は記述ミスがあります。

requirements.txtの作成

開発しているDjangoプロジェクトで利用しているパッケージのメモをとります。これにはプロジェクトフォルダをカレントディレクトリとして次のコマンドを入力します。

pip freeze > requirments.txt

requirments.txtが生成されます。中身はプロジェクトで利用している全てのパッケージが一行ごとに記載されています。

gitの作業

以下の作業が済んでいる前提で記事を進めています。

Gitのインストール

https://howahowablog.com/git-install/

Gitの設定

https://howahowablog.com/git-config/

Githubへプロジェクトをpushする前に、pushの対象から外すファイルを.gitignoreに指定します。(下は参考)

「.gitignore」の中身は、こちらのサイトを利用して基本設定を自動生成して、個別に必要な部分のみ追記します。表示される検索ボックスに「Django」と入力して「作成する」をクリックします。


https://www.toptal.com/developers/gitignore

表示された内容を「Ctrl + A」で全選択して「Ctrl + C」でコピーします。コピーしたら、「.gitignore」ファイルへ「Ctrl + V」でペーストします。

追記したいディレクトリやファイルを入力します。(/authは開発中に個別の設定を行ったファイルを格納していました。/settings_develop.pyはローカル側で利用している情報なのでpushから除外しています。)

プロジェクトをgit initでgit管理下にします。(開発時にすでにGit管理下にしていればこの作業は必要ありません。)

git add .で「.gitignore」に記述されたファイル以外をステージングエリアへ追加します。ステージングエリアに追加されるとファイルの横のアルファベットが「U」から「A」に変わります。

Githubへのプロジェクトの追加

以下の作業が済んでいる前提で記事を進めています。

Githubの登録

https://howahowablog.com/github-account-registration/

秘密鍵の作成方法とGithubへの秘密鍵の登録

https://howahowablog.com/connect-to-github-using-ssh/

リモートリポジトリの作成

https://howahowablog.com/make-remoto-repository/

今回のリモートリポジトリの名前は「howahowablog/Pos」として「Private」で作成しています。

この記事での接続状態です。

次に、git branchコマンドを実行します。「mainブランチ」が選択されていない場合は、git checkout mainコマンドを入力します。

ここまで終えたら次の2つのコマンドを入力します。

git fetch originコマンド

git merge –allow-unrelated-histories origin/mainコマンド

上のコマンドについては次の記事を参考にしてください。

https://howahowablog.com/synchronizing-remote-repositories/

git commit コマンドを利用してコミットします。

git commit -m “django pos commit”コマンドを入力

git push origin mainコマンドでリモートリポジトリへプッシュします。

無事にpushが完了しました。

サーバー側(本番環境側)での作業

サーバー側での必要な作業は次の通りです。

  1. Virtual BoxにRocky Linux を準備する
  2. DBMS(この記事ではPostgreSQL)のインストールと設定
  3. gitのインストールと設定
  4. Githubからプロジェクトをクローンする
  5. python仮想環境の準備
  6. gunicornのインストールと設定
  7. Webサーバー(この記事ではnginx)のインストールと設定

Rocky Linuxの準備

VirtualBoxに、Rocky Linux 9 を準備します。この記事では「Minimal」のイメージをインストールして、Cockpitを有効化しています。また、一般ユーザーで「django」ユーザーを作成しています。

VirtualBoxのインストール方法はこちら

Virtual Box & Linux(Part.1)| Virtual Boxのインストール(Windows版)| 現役エンジニア&プログラミングスクール講師Virtual BoxのWindowsへのインストール方法について記事にしています。Virtual Boxのインストーラーの選択方法、インストーラーのダウンロード、インストーラーの起動とインストール手順、インストール後のVirtual Boxの起動方法と終了方法について扱っています。...

Rocky Linux 9のインストール方法はこちら(今回の記事ではソフトウェアの設定は標準ツールのみ選択し、ストレージ設定は自動生成で完了をしています。)

Virtual Box & Linux(Part.2)| Rocky Linuxのインストール | 現役エンジニア&プログラミングスクール講師Virtual BoxsへのRocky Linuxのインストール方法について記事にしています。Rocky LinuxのIOSイメージファイルのダウンロード方法、Virtual Boxでの仮想マシンの作成方法、Rocky Linuxインストール手順と設定方法について扱って います。...

Cockpitの有効化についてはこちら

Virtual Box & Linux(Part.3)| Linux管理ツール「Cockpit」の有効化 | 現役エンジニア&プログラミングスクール講師Linux管理ツール「Cockpit」の有効化について記事にしています。Linuxをインストールして最初に行う確認や設定の内、Cockpitの有効化を扱っています。その他ファイヤーウォールの確認とSELinuxの確認を行っています。...

サーバ側に必要なソフトウェアは次の5つです。

  1. データベース(この記事ではPostgreSQL)
  2. git
  3. pythonとpython仮想環境(Rocky Linux では標準でインストールされています。)
  4. gunicorn
  5. Webサーバー(この記事ではnginx)

ソフトウェアインストール前の準備

ルートユーザーに切り替えます。
[django@localhost ~]$ su –
Password:

dnfのパッケージリストを格納したデータベースを事前に保存します。
[root@localhost ~]# dnf makecache

全てのパッケージをアップデートします。
[root@localhost ~]# dnf update -y

Linuxを再起動します。
[root@localhost ~]# reboot

再起動後、再度サインインしてルートユーザーに切り替えます。

PostgreSQLの準備

データベースのインストール

PostgreSQLのインストールは次のリファレンスを参考にして行います。

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/9/html/configuring_and_using_database_servers/installing-postgresql_using-postgresql

今回のRocky Linux 9が標準で利用するPostgreSQLのバージョンを確認する場合は次のコマンドを入力します。
[root@localhost ~]# dnf info postgresql-server
違うバージョンを利用する場合はリファレンスに従ってください。

PostgreSQL サーバーパッケージをインストールします。

[root@localhost ~]# dnf install postgresql-server

Is this okと聞かれるので「y」と入力します。

Is this ok [y/N]: y

インストールが完了します。

データベースの設定

PostgreSQLの設定は次のリファレンスを参考にして行います。

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/9/html/configuring_and_using_database_servers/con_postgresql-users_using-postgresql

データベースクラスターを初期化します。

[root@localhost ~]# postgresql-setup –initdb

設定ファイルの編集を行います。

[root@localhost ~]# vi /var/lib/pgsql/data/postgresql.conf

viエディタのコマンドモードで「/password」として「#password_encryption = md5」の行を検索します。

検索後「Enterキー」を押下して、「i」を押下します(インサートモードに切り替えます)。該当箇所を次のように編集します。

password_encryption = scram-sha-256

コマンドモードに切り替えて保存します。(「:wq」で上書き保存し終了します。)

続けて「pg_hba.conf」の設定を行います。

[root@localhost ~]# vi /var/lib/pgsql/data/pg_hba.conf

IPv4 local connections:の最後の部分(一番右側の設定)を
「ident」から「scram-sha-256」に変更します。

コマンドモードに切り替えて保存します。(「:wq」で上書き保存し終了します。)

postgresql サービスを起動します。

[root@localhost ~]# systemctl start postgresql.service

エラーが表示されなければ起動しています。
systemctl status postgresql.serviceで稼働しているかの確認もできます。

postgres という名前のシステムユーザーとしてログインします。(postgres はPostgreSQLをインストールした時から準備されているユーザーです。)

[root@localhost ~]# su – postgres

プロンプトが切り替わります。

[postgres@localhost ~]$

PostgreSQL インタラクティブターミナルを起動します。

[postgres@localhost ~]$ psql
psql (13.11)
Type “help” for help.

Postgreのインタラクティブターミナルが起動しプロンプトが次のようになります。

postgres=#

現在のデータベース接続に関する情報を取得するには次のように入力します。
プロンプト上では「¥」はバックスラッシュで表示されます。

postgres=# \conninfo

djangoで利用する「ユーザー」と「パスワード」を作成します。下のSQL文の赤文字部分がそれぞれ「ユーザー」と「パスワード」になります。

文法
postgres=# CREATE USER mydbuser WITH PASSWORD ‘mypasswd’;

この記事では「ユーザー」をdjangouser、「パスワード」を ‘password’として設定します。本来であればパスワードは推測されにくいもので作ります。

postgres=# CREATE USER djangouser WITH PASSWORD ‘password’;

djangodatabase という名前のデータベースを作成します。

postgres=# CREATE DATABASE djangodatabase;

djangouserへ権限を付与します。

postgres=# GRANT ALL PRIVILEGES ON DATABASE djangodatabase TO djangouser;

\q メタコマンドを使用して、インタラクティブターミナルからログアウトします。

postgres-# \q

postgres ユーザーセッションからログアウトします。

[postgres@localhost ~]$ logout

djangouserとして PostgreSQL ターミナルにログインし、ホスト名を指定して、初期化中に作成されたデフォルトの postgres データベースに接続します。

PostgreSQLを再起動します。

[root@localhost ~]# systemctl restart postgresql.service

新しく作成したユーザーでログインします。
[root@localhost ~]# psql -U djangouser -h 127.0.0.1 -d djangodatabase

パスワードを入力します。
Password for user djangouser:password
psql (13.11)
Type “help” for help.

プロンプトが変わります。

djangodatabase =>

タイムゾーンをDjangoと合わせます。

djangodatabase => ALTER ROLE djangouser SET timezone TO ‘UTC’;

\q メタコマンドを使用して、インタラクティブターミナルからログアウトして、Rocky Linux 9 のルートユーザーに戻ります。

djangodatabase => \q

プロンプトが切り替わります。

[root@localhost ~]#

Postgreデータベースの設定は以上です。

データベースに関わる「settings.py」の編集

viエディタで「settings.py」(この記事では「settingsフォルダの中のsettings_product.pyファイル」)を開き、「DATABASES」部分を次のように編集します。

from .base import *

# SECURITY WARNING: keep the secret key used in production secret!
# 何も入力しません。
SECRET_KEY = ''
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False

#この部分には本番環境でのIPアドレスを入れます。現在は「*」としています。
ALLOWED_HOSTS = [" * "]

# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'djangodatabase',   # データベース名
        'USER': 'djangouser',       # ユーザー名
        'PASSWORD': 'password',     # パスワード
        'HOST': '"127.0.0.1',        # ループバックアドレス
        'PORT': '5432',             # ポート番号:5432
    }
}

設定は以上です。

gitの準備

gitのインストールと設定

Rocky Linux 9 へのGitのインストールについてはこちらを参考にして行います。但し、インストール時のコマンドは「yum」ではなく「dnf」を利用しています。

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/6/html/developer_guide/collaboration.git#doc-wrapper

ルートユーザーに切り替えます。

[django@localhost ~]$ su –
Password:
[root@localhost ~]# dnf install git

インストールが始まります。

途中で「Is this ok」と聞かれるので「y」と入力します。

Total download size: 14 M
Installed size: 61 M
Is this ok [y/N]:y

インストールが完了します。

デフォルトのテキストエディターの設定(この記事ではviとしています。)

[root@localhost ~]# git config –global core.editor vi

ユーザー情報の登録(下は例です。実際の情報に置き換えて入力します。この記事でもユーザー名とメールアドレスは個人のもので入力しています。)
[root@localhost ~]# git config –global user.name “John Doe
[root@localhost ~]# git config –global user.email “john@example.com

サーバー上にリモートリポジトリのクローン先ディレクトリを作成します。作成先はRocky Linux のインストール時に作成した「djangoユーザー」のhome/djangoディレクトリの直下にしています。名前は「pos」で作成しています。

[root@localhost ~]# exit
logout
[django@localhost ~]$ mkdir pos

posディレクトリに移動します。
[django@localhost ~]$ cd pos

プロンプトが切り替わります。
[django@localhost pos]$

接続用の鍵を生成します。

[django@localhost pos]$ ssh-keygen -t ed25519 -C “john@example.com
Generating public/private ed25519 key pair.

次は何も入力せずにEnterキーを押下します。
Enter file in which to save the key (/home/django/.ssh/id_ed25519):

パスフレーズを入力します。忘れないようにします。
Created directory ‘/home/django/.ssh’.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:

生成した鍵はユーザーディレクトリ内の隠しディレクトリ「.ssh」に保存されています。次のコマンドで鍵が存在しているかを確認します。

[django@localhost pos]$ ls -al ~/.ssh

次のコマンドで鍵を表示してコピーします。(CockpitでLinux操作を行っている場合はコピーしたいプロンプト上の文字部分を選択して右クリックで簡単にコピーができます。(鍵の追加方法については次の記事を参考にしてください。)

https://howahowablog.com/connect-to-github-using-ssh/

catコマンドで表示した鍵をマウスで選択して右クリック「Copy」します。

[django@localhost pos]$ cat ~/.ssh/id_ed25519.pub
ssh-ed25519 AA************************************john@example.com

コピーした鍵をGithubに登録します。

Githubへの接続ができるか確認します。ホームディレクトリから次のコマンドを入力します。

[django@localhost ~]$ ssh -T git@github.com

接続していいかを問われるので「yes」と入力します。

Are you sure you want to continue connecting (yes/no/[fingerprint])? yes

パスフレーズを聞かれます。

Enter passphrase for key ‘/home/django/.ssh/id_ed25519’:(パスフレーズを入力)

パスフレーズを入力して次のように表示されればSSH接続の設定が正しく行えたことになります。
Hi howahowablog! You’ve successfully authenticated, but GitHub does not provide shell access.

作成したposディレクトリをgitの配下に置きます。

[django@localhost ~]$ cd pos
[django@localhost pos]$ git init
hint: Using ‘master’ as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint: git config –global init.defaultBranch
hint:
hint: Names commonly chosen instead of ‘master’ are ‘main’, ‘trunk’ and
hint: ‘development’. The just-created branch can be renamed via this command:
hint:
hint: git branch -m

Initialized empty Git repository in /home/django/pos/.git/

[django@localhost pos]$ ls -la
total 0
drwxr-xr-x. 3 django django 18 Oct 14 02:49 .
drwx——. 4 django django 127 Oct 14 02:07 ..
drwxr-xr-x. 7 django django 119 Oct 14 02:49 .git
.gitディレクトリが作成されたのが確認できます。

次のコマンドで利用したいリモートリポジトリを登録します。

git remote add <URLの別名><接続先のリモートリポジトリのURL>コマンド

[django@localhost pos]$ git remote add origin リモートリポジトリのURL

次のコマンドでリモートリポジトリのプロジェクトをサーバーにクローンします。

[django@localhost pos]$ git clone リモートリポジトリのURL
Cloning into ‘Pos’…
Enter passphrase for key ‘/home/django/.ssh/id_ed25519’:(パスフレーズを入力)
remote: Enumerating objects: 216, done.
remote: Counting objects: 100% (216/216), done.
remote: Compressing objects: 100% (103/103), done.
remote: Total 216 (delta 87), reused 212 (delta 86), pack-reused 0
Receiving objects: 100% (216/216), 87.20 KiB | 273.00 KiB/s, done.
Resolving deltas: 100% (87/87), done.

以上でRocky Linux 9内にローカルで開発したDjangoのプロジェクトを呼び込むことができました。

python仮想環境の準備

Rocky Linux上でpython仮想環境を作成

Rocky Linux 9 にはすでにpython3.9がインストールされているので、これを利用してpython仮想環境を作成します。

次のコマンドでGithubからクローンしたPosプロジェクトが確認できます。このプロジェクトディレクトリをカレントディレクトリとして仮想環境を作成します。
[django@localhost pos]$ ls
Pos

Posプロジェクトへ移動します。
[django@localhost pos]$ cd Pos
中身を確認します。main.pyがあることを確認します。
[django@localhost Pos]$ ls
README.md main.py pos requirements.txt

pythonがインストールされているか、どのバージョンか、複数存在するかなどを念のため確認します。
[django@localhost Pos]$ python -V
Python 3.9.16

venvを利用してpython仮想環境「env(名前はenvでなくても構いません)」を作成します。
[django@localhost Pos]$ python3 -m venv env
中身を確認します。
[django@localhost Pos]$ ls
envが確認できます。
README.md env main.py pos requirements.txt

python仮想環境を立ち上げます。
[django@localhost Pos]$ source env/bin/activate
プロンプトが変わりpython仮想環境が立ち上がったのが確認できます。
(env) [django@localhost Pos]$

インストールされているパッケージを出力(メモするため)できる「freeze」をpipを利用してインストールします。(今後、本番環境内でいろいろなパッケージをインストールするため、そのメモをとるのにfreezeが必要になります。)
(env) [django@localhost Pos]$ pip freeze

ひとまず、Githubからクローンしたプロジェクトにあるrequirements.txtを利用して必要なパッケージをインストールします。これで開発環境側で利用していたパッケージと同じパッケージを同じバージョンで全てインストールできます。

(env) [django@localhost Pos]$ pip install -r requirements.txt

インストール後に次の表示が出た場合はpipをアップグレードしておきます。

(env) [django@localhost Pos]$ python3 -m pip install –upgrade pip

シークレットキーの生成と設定

続けて、本番環境用のシークレットキーを生成して「settings_product.py」に登録します。

manage.pyのあるディレクトリに移動してインタラクティブシェルを起動します。

(env) [django@localhost Pos]$ cd pos
(env) [django@localhost pos]$ python manage.py shell
Python 3.9.16 (main, Sep 12 2023, 00:00:00)
[GCC 11.3.1 20221121 (Red Hat 11.3.1-4)] on linux
Type “help”, “copyright”, “credits” or “license” for more information.
(InteractiveConsole)

シークレットキーの再生成をします。

>>> from django.core.management.utils import get_random_secret_key

>>>get_random_secret_key()

鍵が生成されるのでクリップボードにコピーします。(Cockpitのターミナルだと右クリックでコピーができます。)

‘xv!*********************************************7@f)’

次のコマンドでpython仮想環境に戻ります。

>>> exit()

python仮想環境に戻ったら、viエディタを利用して「settingsディレクトリ」内の「settings_product.pyファイル」にある「SECRET_KEY」部分に貼り付けます。

os.environを利用して環境変数からの取り出しもできますが、今回は直接貼り付けています。

from .base import *

# SECURITY WARNING: keep the secret key used in production secret!
# 新しいシークレットキーを設定します。
SECRET_KEY = 'xv!*********************************************7@f)'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False

#この部分には本番環境でのIPアドレスを入れます。現在は「*」としています。
ALLOWED_HOSTS = [" * "]

# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'djangodatabase',   # データベース名
        'USER': 'djangouser',       # ユーザー名
        'PASSWORD': 'password',     # パスワード
        'HOST': '"127.0.0.1',        # ループバックアドレス
        'PORT': '5432',             # ポート番号:5432
    }
}

pythonからPostgreSQLに接続するためのモジュールのインストール

python仮想環境が作成とシークレットキーの設定ができたので、ここで初めて、pythonからPostgreSQLに接続するためのモジュールをpipを利用してインストールします。(この記事ではビルド済みの「psycopg2-binary」をインストールします。)

(env) [django@localhost Pos]$ pip install psycopg2-binary

python仮想環境を終了します。

(env) [django@localhost pos]$ deactivate

ルートユーザーに切り替えてPostgreSQLの稼働状況を確認します。

[django@localhost pos]$ su –
Password:
[root@localhost ~]# service postgresql status

以下のように表示された場合は、起動する必要があります。
Redirecting to /bin/systemctl status postgresql.service
○ postgresql.service – PostgreSQL database server
Loaded: loaded (/usr/lib/systemd/system/postgresql.service; disabled; preset: disabled)
Active: inactive (dead)

PostgreSQLを起動します。

[root@localhost ~]# systemctl start postgresql.service

ルートユーザーを抜けて再度、python仮想環境を起動します。
[root@localhost ~]# exit
logout

python仮想環境「env」を持っているディレクトリに移動します。
(この記事では「Pos」ディレクトリです。)
[django@localhost pos]$ cd ../

python仮想環境を起動します。
[django@localhost Pos]$ source env/bin/activate

「manage.py」があるディレクトリに移動します。(この記事では「Posプロジェクト」直下の「posディレクトリ」となります。)
(env) [django@localhost Pos]$ cd pos

データベースのアクセスをチェックします。
(env) [django@localhost pos]$ python manage.py check –database default
System check identified no issues (0 silenced).

マイグレーションします。
(env) [django@localhost pos]$ python manage.py makemigrations
No changes detected
(env) [django@localhost pos]$ python manage.py migrate

Djangoアプリケーションのスーパーユーザーを作成します。

(env) [django@localhost pos]$ python manage.py createsuperuser
ユーザー名 (leave blank to use ‘django’): admin

この記事ではユーザー名をadminとしていますが、名前は自由に決めれます。


メールアドレス:
Password: ←パスワードを入力
Password (again): ←確認としてパスワードを再度入力
このパスワードは ユーザー名 と似すぎています。
このパスワードは短すぎます。最低 8 文字以上必要です。
このパスワードは一般的すぎます。

Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.
(env) [django@localhost pos]$

ここまでで、DjangoとPostgreSQLの連携の設定が終了しました。

Gunicornの準備

Gunicornのインストールと設定①

Djangoの実行にはGunicornというソフトウェアが必要です。これは「PythonのWeb Server Gateway Interface(WSGI)を実装するHTTPサーバー」です。DjangoアプリケーションとWebサーバー間のインターフェースとして機能してくれます。

python仮想環境(この記事ではenv)を持つディレクトリ(この記事ではPosディレクトリ)に移動してGunicornをインストールします。

(env) [django@localhost Pos]$ pip install gunicorn

インストール後、Gunicornを利用してDjangoアプリケーションが実行できるかを確認します。そのために一時的に任意のポート(この記事では8000番)のファイアウォールを開放します。

ルートユーザーに切り替え次のコマンドを入力します。(一般ユーザーからsudoを付けて実行も可能です。)

(env) [django@localhost pos]$ deactivate
[django@localhost pos]$ su –
Password:
[root@localhost ~]# firewall-cmd –add-port=8000/tcp –permanent
success
[root@localhost ~]# firewall-cmd –reload
success

ルートユーザーを抜けてpython仮想環境に戻ります。
[django@localhost Pos]$ source env/bin/activate
(env) [django@localhost Pos]$ cd pos

viエディタで「settings_product.py」を開いて「ALLOWED_HOSTS」に本番環境で利用するIPアドレスを入力します。IPアドレスは「ifconfig」コマンドで確認します。この記事作成時の筆者の環境では「192.168.2.155」でした。(固定IPアドレスにするのが望ましいですが、デプロイの流れを確認する記事なので固定IPアドレスの設定は行っていません。)

from .base import *

# SECURITY WARNING: keep the secret key used in production secret!
# 新しいシークレットキーを設定します。
SECRET_KEY = 'xv!*********************************************7@f)'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False

# 環境によって変更
ALLOWED_HOSTS = ["192.168.2.155 "]

# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'djangodatabase',   # データベース名
        'USER': 'djangouser',       # ユーザー名
        'PASSWORD': 'password',     # パスワード
        'HOST': '127.0.0.1',        # localhost
        'PORT': '5432',             # 5432
    }
}

settingsフォルダ内のbase.pyに次の4行を追記します。
(「base.py」は「元settings.py」)

import os

STATIC_ROOT = os.path.join(BASE_DIR, ‘static’)

MEDIA_URL = ‘/media/’

MEDIA_ROOT = os.path.join(BASE_DIR, ‘media’)

from pathlib import Path
# ここがひとつ目#######################
import os

BASE_DIR = Path(__file__).resolve().parent.parent.parent

INSTALLED_APPS = [
    'monthlyaccount.apps.MonthlyaccountConfig',
    'depositbook.apps.DepositbookConfig',
    'cashbook.apps.CashbookConfig',
    'accountlist.apps.AccountlistConfig',
    'consumptiontax.apps.ConsumptiontaxConfig',
    'dailyaccount.apps.DailyaccountConfig',
    'bills.apps.BillsConfig',
    'customerlist.apps.CustomerlistConfig',
    'menulist.apps.MenulistConfig',
    'mainpage.apps.MainpageConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

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 = 'pos.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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 = 'pos.wsgi.application'

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',
    },
]

LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
USE_I18N = True
USE_TZ = True

STATIC_URL = '/static/'
# ここがふたつ目#######################
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
# ここがみっつ目#######################
MEDIA_URL = '/media/'
# ここがよっつ目#######################
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

ここまで入力ができると、WSGIサーバーからのレスポンスを確認できます。次のように入力してALLOWED_HOSTSに指定しているアドレスにファイアウォールで許可したポートを付加してブラウザでアクセスします。

起動します。

(env) [django@localhost pos]$ gunicorn –bind 0.0.0.0:8000 pos.wsgi:application

この記事の場合は「192.168.2.155:8000」でアクセスします。

ブラウザで次のように表示されました。

今はまだCSSが適用されていませんが、nginxをインストールして設定するときに設定を編集します。その事前準備としてプロジェクト内の静的ファイルを収集します。これは、先ほどbase.pyに追記した「STATIC_ROOT = os.path.join(BASE_DIR, ‘static’)」と「MEDIA_ROOT = os.path.join(BASE_DIR, ‘media’)」によって収集する箇所を指定しています。

(env) [django@localhost pos]$ python manage.py collectstatic

150 static files copied to ‘/home/django/pos/Pos/static’.

staticフォルダを確認できます。

(env) [django@localhost Pos]$ ls
README.md env main.py pos requirements.txt static

(env) [django@localhost Pos]$ ls static/
accountlist bills consumptiontax dailyaccount mainpage monthlyaccount
admin cashbook customerlist depositbook menulist

開いたファイアウォールを閉じておきます。
(env) [django@localhost pos]$ deactivate
[django@localhost pos]$ su –
Password:
[root@localhost ~]# firewall-cmd –remove-port=8000/tcp –permanent
success
[root@localhost ~]# firewall-cmd –reload
success

Webサーバー(nginx)の準備

Webサーバーソフトのインストールとファイアウォールの設定

Webサーバーの「nginx」をインストールします。

[root@localhost ~]# dnf install nginx

Total download size: 640 k
Installed size: 1.8 M
Is this ok [y/N]: y

Rocky Linux を起動したときにnginxも自動で起動するように設定します。

[root@localhost ~]# systemctl enable nginx

nginxを起動します。

[root@localhost ~]# systemctl start nginx
[root@localhost ~]# systemctl status nginx

ファイアウォールの設定から80番ポートを開きます。

[root@localhost ~]# firewall-cmd –add-service=http –permanent
success

[root@localhost ~]# firewall-cmd –reload
success

Gunicornの設定②

gunicorn設定ファイル(「gunicorn.socket」と「gunicorn.service」)の作成と設定を行います。Rocky Linux で設定ファイルは/etc/systemd/systemディレクトリに作成します。

[root@localhost ~]# vi /etc/systemd/system/gunicorn.socket

[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target

[root@localhost ~]# vi /etc/systemd/system/gunicorn.service

(注意)ExecStartの箇所でフォルダの移動を指定しています。必須ではありませんが、この記事の場合「pos.wsgi:application」の場所が深いため、移動の設定が必要になります。
–chdir /home/django/pos/Pos/pos

次の部分はwsgiの準備されているディレクトリを指定して、
ディレクトリ名.wsgi:application」と記述します。
今回の記述例: pos.wsgi:application

[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=django
Group=django
WorkingDirectory=/home/django/pos/Pos/pos/pos
ExecStart=/home/django/pos/Pos/env/bin/gunicorn --workers 3 --bind unix:/run/gunicorn.sock --chdir /home/django/pos/Pos/pos pos.wsgi:application

[Install]
WantedBy=multi-user.target

新規作成した設定ファイルが読み込まれるようにreloadします。

[root@localhost ~]# systemctl daemon-reload

[root@localhost ~]# systemctl start gunicorn.socket
[root@localhost ~]# systemctl enable gunicorn.socket
Created symlink /etc/systemd/system/sockets.target.wants/gunicorn.socket → /etc/systemd/system/gunicorn.socket.

[root@localhost ~]# systemctl status gunicorn.socket

Webサーバーの設定

Gunicornの設定ファイルが作成できたので、最後にWebサーバー(この記事ではnginx)の設定を行います。

設定ファイル(nginx.conf)を開いて次の一行を追記します。これはサーバーの名前が長すぎるときにエラーを吐き出さないようにするために追記します。

[root@localhost ~]# vi /etc/nginx/nginx.conf

http {}の中にserver_names_hash_bucket_size 64;

続けて「nginx.conf」に呼び込まれるオリジナルの設定ファイルを作成します。

「nginx.conf」にはinclude /etc/nginx/conf.d/*.conf;という記述があり、「/etc/nginx/conf.dディレクトリ」内に作成した〇〇.confというファイルを読み込めるように仕組まれています。

この記事では「djangoapp.conf」という名前で作成しています。

[root@localhost ~]# vi /etc/nginx/conf.d/djangoapp.conf

server {
    listen 80 default_server;
    server_name 192.168.2.155;

    location /static/ {
        root /home/django/pos/Pos;
    }

    location /media/ {
        root /home/django/pos/Pos;
    }

    location / {
        # gunicorn.socketを作成するとRocky Linux のrunディレクトリにgunicorn.sockというファイルが自動で生成されます。
        proxy_pass http://unix:/run/gunicorn.sock;
        # ホスト名が呼ばれます。
        proxy_set_header Host $http_host;
        # 送信元のアドレスが呼ばれます。
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect off; 
    }
}

設定ファイルのテストを行います。

[root@localhost ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

何かしらの間違いがある場合は設定ファイルの行数を出力してくれます。(下の例では「gunicorn.socket」の14行目にミスがあります。)

Gunicornの設定ファイルの再読み込みとnginxの再起動を行います。

[root@localhost ~]# systemctl restart gunicorn.socket
[root@localhost ~]# systemctl restart gunicorn.service
[root@localhost ~]# systemctl reload nginx.service

上の3つのコマンドを入力するときにエラーが出た場合は次のコマンドを入力してから打ち直します。
[root@localhost ~]# systemctl daemon-reload

SELinuxの設定を変更します。

[root@localhost ~]# vi /etc/selinux/config

Rocky Linux を再起動して、忘れずにPostgreSQLも起動します。

[root@localhost ~]# reboot

[django@localhost ~]$ su –
Password:
[root@localhost ~]# systemctl start postgresql.service
[root@localhost ~]#

指定したIPアドレスへアクセスします。(今回は192.168.2.155)

PCでの表示

スマートフォンでの表示はうまくいっていません。Rocky Linux のhome/djangoディレクトリに、その他のユーザーの実行権限を付与します。

ホームディレクトリのその他のユーザーへの実行権限の付与

[root@localhost ~]# ls
anaconda-ks.cfg
[root@localhost ~]# cd ../
[root@localhost /]# ls
afs boot etc lib media opt root sbin sys usr
bin dev home lib64 mnt proc run srv tmp var
[root@localhost /]# cd home
[root@localhost home]# ls -l
total 4
drwx—–. 5 django django 4096 Oct 15 13:52 django
[root@localhost home]# chmod 701 django/
[root@localhost home]# ls -l
total 4
drwx—–x. 5 django django 4096 Oct 15 13:52 django
[root@localhost home]#

スマートフォンで再度アクセスします。今度はCSSが適用されています。

その他、このような表示になった場合は

502 Bad Gatewayが表示されたら「gunicorn.socket」や「gunicorn.service」の設定ミスが疑えます。その他にもnginxの新規に作成した.confも確認します。

その他にも、うまくいかない場合に次の権限付与も検討します。

「manage.py」に755の権限を付与します。

[root@localhost pos]# chmod 755 manage.py

Djangoのデプロイ作業については以上となります。

ブックマークのすすめ

「ほわほわぶろぐ」を常に検索するのが面倒だという方はブックマークをお勧めします。ブックマークの設定は別記事にて掲載しています。

「お気に入り」の登録・削除方法【Google Chrome / Microsoft Edge】「お気に入り」の登録・削除方法【Google Chrome / Microsoft Edge】について解説している記事です。削除方法も掲載しています。...
【パソコン選び】失敗しないための重要ポイント | 現役エンジニア&プログラミングスクール講師【パソコン選び】失敗しないための重要ポイントについての記事です。パソコンのタイプと購入時に検討すべき点・家電量販店で見かけるCPUの見方・購入者が必要とするメモリ容量・HDDとSSDについて・ディスプレイの種類・バッテリーの持ち時間や保証・Officeソフト・ウィルス対策ソフトについて書いています。...
RELATED POST
06-Django

Django デプロイ(5)|「Django」が学べる ITスクール情報|現役エンジニア&プログラミングスクール講師

2023年10月17日
プログラミング学習 おすすめ書籍情報発信 パソコン初心者 エンジニア希望者 新人エンジニア IT業界への就職・転職希望者 サポートサイト Programming learning Recommended schools Recommended books Information dissemination Computer beginners Prospective engineers New engineers Prospective job seekers in the IT industry Support site
06-Django

Django デプロイ(3)|「Django」が学べる ITスクール情報|現役エンジニア&プログラミングスクール講師

2023年10月15日
プログラミング学習 おすすめ書籍情報発信 パソコン初心者 エンジニア希望者 新人エンジニア IT業界への就職・転職希望者 サポートサイト Programming learning Recommended schools Recommended books Information dissemination Computer beginners Prospective engineers New engineers Prospective job seekers in the IT industry Support site
06-Django

Django デプロイ(4)|「Django」が学べる ITスクール情報|現役エンジニア&プログラミングスクール講師

2023年10月16日
プログラミング学習 おすすめ書籍情報発信 パソコン初心者 エンジニア希望者 新人エンジニア IT業界への就職・転職希望者 サポートサイト Programming learning Recommended schools Recommended books Information dissemination Computer beginners Prospective engineers New engineers Prospective job seekers in the IT industry Support site
06-Django

Django デプロイ(1)|「Django」が学べる ITスクール情報|現役エンジニア&プログラミングスクール講師

2023年10月13日
プログラミング学習 おすすめ書籍情報発信 パソコン初心者 エンジニア希望者 新人エンジニア IT業界への就職・転職希望者 サポートサイト Programming learning Recommended schools Recommended books Information dissemination Computer beginners Prospective engineers New engineers Prospective job seekers in the IT industry Support site
06-Django

Django デプロイ(2)|「Django」が学べる ITスクール情報|現役エンジニア&プログラミングスクール講師

2023年10月14日
プログラミング学習 おすすめ書籍情報発信 パソコン初心者 エンジニア希望者 新人エンジニア IT業界への就職・転職希望者 サポートサイト Programming learning Recommended schools Recommended books Information dissemination Computer beginners Prospective engineers New engineers Prospective job seekers in the IT industry Support site