06-Django

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

Django デプロイ作業(Part.6)

この記事では「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)のインストールと設定

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

この記事は第5回目からの続きの操作となっています。

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 デプロイ(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 デプロイ(まとめ)|「Django」が学べる ITスクール情報|現役エンジニア&プログラミングスクール講師

2023年10月12日
プログラミング学習 おすすめ書籍情報発信 パソコン初心者 エンジニア希望者 新人エンジニア 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 デプロイ(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 デプロイ(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