自動化無しに生活無し

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

UbuntuにDjangoをデプロイする【PostgreSQL+Nginx、Virtualenv使用】

thumbnail

Ubuntuのデプロイ時にVirtualenvを使う。

以前の方法はOSに直接Djangoなどのライブラリをインストールしているため、OSの更新と同時にライブラリも更新されてしまう。

Virtualenvを使えば、OSを更新してもライブラリのバージョンは常に一定。手動で更新する仕様になる。

Djangoプロジェクトの配置

下記になるよう配置する。

/home/[ユーザー名]/Documents/[プロジェクト名]/

PostgreSQLとNginxのインストール

sudo apt install postgresql nginx

PostgreSQLは下記を見て、ユーザーとDBを作る。

PostgreSQLインストールから、ユーザーとDBを作る

必要なライブラリのインストール

デプロイに必要なライブラリは下記コマンドでインストールできる。実質PostgreSQLにアクセスするためのpsycopg2とNginxとPythonをつなぐgunicornだけ。

pip install gunicorn psycopg2 psycopg2-binary

もし、psycopg2のインストールができない場合、以下を実行

sudo apt install libpq-dev python3-dev

requirements.txtがあれば、下記でまとめてインストールしておく。

pip install -r requirements.txt

【補足1】pip3とvirtualenvがインストールされていない場合

python3.x系のPythonパッケージ管理ツールのpip3コマンドと、virtualenvがインストールされていない場合は下記コマンドでインストールする。

sudo apt install python3-pip
sudo pip3 install virtualenv

Djangoのsettings.pyの編集

settings.pyを書き換える。

"""
Django settings for config project.

Generated by 'django-admin startproject' using Django 3.2.9.

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
PROJECT_NAME    = BASE_DIR.name

# 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-vu%_f002fuqsn1dehb+)4cy6xxb1i_i1r3mxu)jp9c^o&#agwq'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False


if DEBUG:
    ALLOWED_HOSTS = [ "" ]
else:
    ALLOWED_HOSTS = ["ここにデプロイ先のIPアドレスを"]


# Application definition
INSTALLED_APPS = [
    '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 = '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

if DEBUG:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': BASE_DIR / 'db.sqlite3',
        }
    }
else:
    #TODO:下記にPostgreSQLのパスワードを
    DATABASES = { 
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': '',
            'USER': '',
            'PASSWORD':'',
            'HOST': 'localhost',
            'PORT': '', 
        }   
    }


# 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


#TODO:静的ファイル、メディアファイルの扱いを書き換える

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/

STATIC_URL          = '/static/'
STATICFILES_DIRS    = [ BASE_DIR / "static" ]

if not DEBUG:
    STATIC_ROOT = f"/var/www/{PROJECT_NAME}/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'


MEDIA_URL   = "/media/"
if DEBUG:
    MEDIA_ROOT  = BASE_DIR / "media"
else:
    MEDIA_ROOT  = f"/var/www/{PROJECT_NAME}/media"

静的ファイル・メディアファイルを格納するディレクトリを作る

下記コマンドを順次実行、公開ディレクトリ内にプロジェクトを作る。

sudo mkdir /var/www/[プロジェクト名]/
sudo chown [ユーザー名]:www-data /var/www/[プロジェクト名]/

systemdにgunicornの自動起動を設定

下記コマンドを実行し、systemdのサービスを作る。

sudo vi /etc/systemd/system/gunicorn.service

内容は下記

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

[Service]
User=[ここにユーザー名]
Group=www-data
WorkingDirectory=/home/[ここにユーザー名]/Documents/[ここにプロジェクト名]
ExecStart       =/home/[ここにユーザー名]/Documents/[ここにプロジェクト名]/venv/bin/gunicorn --access-logfile - --workers 3 \
                 --bind unix:/home/[ここにユーザー名]/Documents/[ここにプロジェクト名]/[ここにプロジェクト名].socket config.wsgi:application

[Install]
WantedBy=multi-user.target

下記コマンドを実行して動かす。

sudo systemctl start gunicorn
sudo systemctl enable gunicorn

下記コマンドでステータスを確認して、動作していればOK

sudo systemctl status gunicorn

Nginxの設定

設定ファイルを作る

sudo vi /etc/nginx/sites-available/[プロジェクト名]

内容は下記

server {
    listen 80;
    server_name [サーバーのIPアドレス];

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /var/www/[プロジェクト名];
    }
    location /media/ {
        root /var/www/[プロジェクト名];
    }
    location / {
        include proxy_params;
        proxy_pass http://unix:/home/[ユーザー名]/Documents/[プロジェクト名]/[プロジェクト名].socket;
    }

    client_max_body_size 100M;
}

シンボリックリンクを作り、設定を有効化させる

sudo ln -s /etc/nginx/sites-available/[プロジェクト名] /etc/nginx/sites-enabled/

もともとあったデフォルトの設定は無効化、Nginxをリロード

#デフォルトの設定ファイルの無効化
sudo unlink /etc/nginx/sites-enabled/default

#nginxの設定をテストする。
sudo nginx -t

#nginxのリロード
sudo systemctl reload nginx

Nginxの動作確認

sudo systemctl status nginx

マイグレーションと静的ファイルの配信

python3 manage.py migrate
python3 manage.py collectstatic

サイトにアクセス。

サーバーのIPアドレスにアクセスする。

【必読】エラーで動かない時の対処法

【必読1】Nginxのログを見る

デフォルトでは/var/log/nginx/error.logに出力されている。詳しくは下記。

Nginxのログをチェックする、ログの出力設定を変更する

【必読2】systemdのログを見る

下記コマンドで、gunicornのログを出力できる

journalctl | grep gunicorn

参照:https://qiita.com/marumen/items/e4c75a2617cb5d0113ce

【必読3】権限が適切かチェックする。VirtualBoxのOSに対してのデプロイは特に注意!!

プロジェクトのディレクトリのアクセス権が適切に割り振られていない場合、502エラーになる。

ls -al ~/Documents/[プロジェクト名]

このコマンドを実行して、[プロジェクト名]にその他のユーザーに対して、実行権限が割り振られていない場合、ディレクトリの実行権限を割り振る。

chmod 755 ~/Documents/[プロジェクト名]

これをやっていない場合、Nginxは[プロジェクト名].socketに対してアクセスできない。

【補足】ドラッグアンドドロップでコピーすると、所有者のみフルアクセスの権限に変わる。

特に注意しなければならないのが、VirtualBoxにインストールしたUbuntuへデプロイをする時。

ドラッグアンドドロップでプロジェクトをコピペする時、ディレクトリのパーミッションが所有者のみ全て許可されており、それ以外のユーザーは実行さえ許されない。

そのため、www-dataがプロジェクトファイルを読み込もうとすると、502エラーが出る。

【必読4】設定ファイルを読み込み、再起動させる

sudo systemctl daemon-reload
sudo systemctl restart nginx gunicorn 
スポンサーリンク

シェアボタン

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