pipenv、Nginx、uWSGI、Djangoでソケット通信とHTTP通信の環境を作る方法

Django

はじめに

この記事ではpipenvを使ってNginx、uWSGI、Djangoの環境を作る方法を説明しています。
ソケット通信で説明しています。
HTTP通信の場合は、他記事にあります。

環境

NginxはDebianで提供されているバージョンを使います。
pipenvの仮想環境で使うPythonとDjangoは最新バージョンを使います。

 - Debian bullseye 64bit
 - Nginx
 - Python
 - Django

ディレクトリ構造は以下の通りです。
uWSGIの設定ファイル「uwsgi.ini」とpipenvの仮想環境ディレクトリ「.venv」はDjangoのプロジェクトを作成したディレクトリに置きます。

Nginx
  /etc/nginx/sites-available/proj.conf

PostgreSQL
  /etc/postgresql/13/main/postgresql.conf

Django
 /home/www/wsgi/proj
   ┣ -- proj
        ┣ -- urls.py
   ┣ -- app
   ┣ -- templates
   ┣ -- static
   ┣ -- db.sqlite3
   ┣ -- uwsgi.log
   ┣ -- uwsgi.ini
   ┣ -- .venv

systemdでuWSGIを自動起動する設定ファイル
  /etc/systemd/system/uwsgi-proj.service

NginxとuWSGIのソケット通信用のディレクトリ
  /run/proj

pyenvのインストールと設定

pipenvを使ってDjangoのプロジェクトを作成したディレクトリに作成します。
pyenvの環境変数をproflileに書き込むのですが書式が変わっています。
「2.Configure your shell’s environment for Pyenv」を参照してください。

GitHub - pyenv/pyenv: Simple Python version management
Simple Python version management. Contribute to pyenv/pyenv development by creating an account on Gi...

はじめにpyenvの環境を整備します。

cd ~/
sudo apt install git

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

~/.bashrc、または~/.profileの最終行に環境変数を追記します。

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"

export WORKON_HOME=~/.venvs
export PIPENV_VENV_IN_PROJECT=true

環境変数を反映させます。

. /home/xxx/.bashrc
または
source /home/xxx/.bashrc

pyenvをアップデートするためのモジュールをインストールします。

git clone https://github.com/yyuu/pyenv-update.git ~/.pyenv/plugins/pyenv-update

pyenvで新しいバージョンのPythonを扱うにはアップデートが必要です。

pyenv update

pipでモジュールをインストールするために必要なパッケージをインストールします。

sudo apt install -y gcc make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev apache2-dev

インストール可能なPythonのリスト表示して、最新バージョンをインストールします。

pyenv install -l | grep '^  3\.[0-9]*\.[0-9]'

pyenv install 3.9.7

Apache2で使う場合は、以下。
env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install 3.9.7

pyenv versions

仮想環境を作成するためにpyenv-virtualenvをインストールします。

git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv

pipenvの設定

上記で作成した仮想環境にpipenvをインストールしてpipをアップグレードします。
「which pipenv」を実行して、パスが現在の仮想環境に存在するか確認します。

pip install pipenv
which pipenv
      /home/hoge/.pyenv/shims/pipenv

Djangoのプロジェクト「proj」を/home/www/wsgi/に作成します。

mkdir /home/www/wsgi/proj

プロジェクト直下に仮想環境を作成してpipenvをインストールします。
ここでも「which pipenv」を実行して、パスが現在の仮想環境に存在するか確認します。

cd /home/www/wsgi/proj
pipenv --python 3.9.7
pipenv shell
pip install --upgrade pip
which pip
  /home/www/wsgi/proj/.venv/bin/pip
pip install pipenv
which pipenv
     /home/www/wsgi/proj/.venv/bin/pipenv

pipenv install django
pipenv install uwsgi

設定ファイルとアプリを作成します。

cd /home/www/wsgi/proj
django-admin startproject config .
django-admin startapp app

移行するパッケージがあればインストールします。

pipenv install -r  ~/req.txt

Nginxの設定

Nginxの設定ファイルをインストールします。
Apacheが動作している場合は停止します。
また、Apacheを使わない場合は、OSの起動時にApacheが動作しないように無効化します。

sudo systemctl stop apache2
sudo systemctl disable apache2
sudo apt install nginx

Nginxの設定ファイルを編集します。

sudo vi /etc/nginx/sites-available/proj

「server_name」はホスト名でもIPアドレスのとちらでも良いです。
Djangoのstaticファイルはcollectstaticでまとめていなので、Nginxの設定ファイルでadminのstaticファイルを別に指定します。

server {
    listen 80;
    server_name aaa.bbb.ccc.ddd;
    charset utf-8;

    # max upload size
    client_max_body_size 200M;

    # access limit
    allow 192.168.10.4;
    allow 192.168.10.0/24;
    deny all;

    # Django admin static file
    location /static/admin {
       alias /home/www/wsgi/proj/.venv/lib/python3.9/site-packages/django/contrib/admin/static/admin/;
    }
	
    location /static {
       alias /home/www/wsgi/proj/static;
    }

    # making file and download for Django
    location /proj_file {
       alias /home/www/html/proj_file;
    }

   #location /media {
      #alias /usr/share/nginx/html/media;
   #}
 
  # 「/proj」の場合は、Djangoのurls.pyの修正が必要。
  #location / {
    location /proj {
       include uwsgi_params;

       # Socket
       uwsgi_pass unix:/run/proj/uwsgi-proj.sock;

       # HTTP
      #proxy_pass http://127.0.0.1:8900;
      #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      #proxy_set_header Host $http_host;
      #proxy_redirect off;
      #proxy_set_header X-Forwarded-Proto $scheme;
    }


   #location / {
   #     root /home/www/html;
   # }
}

Nginxを再起動します。

cd /etc/nginx/sites-enabled
sudo rm -i default
sudo ln -s /etc/nginx/sites-available/proj .
sudo systemctl restart nginx

Djangoのurls.pyの修正

Nginxの設定ファイルでDjangoのrootディレクトリが「/」でない場合は、urls.pyの修正が必要です。

cd /home/www/wsgi/proj/proj
vi urls.py

Nginxの設定ファイルで「/proj」にした場合、以下のようにパスの先頭にprojを追記します。

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('proj/admin/', admin.site.urls),

   #path('admin/', admin.site.urls),
]

uWSGIの設定

Djangoプロジェクトのディレクトリに「uwsgi.ini」ファイルを作成します。
設定ファイルを「django-admin startproject config .」で作成しているので、「module = config.wsgi:application」のように「config」と指定します。

[uwsgi]
chdir  = /home/www/wsgi/proj
module = config.wsgi:application
home   = .venv
master = true

py-autoreload = 1
die-on-term   = true

enable-threads = true
processes      = 1
max-requests   = 5000
buffer-size    = 65536

uid = www-data
gid = www-data

logto      = uwsgi.log
deamonize  = uwsgi-@(exec://date +%Y-%m-%d).log
#daemonize = uwsgi-daemon.log
log-reopen = true

#
# Socket
#
socket       = /run/proj/uwsgi-proj.sock
chmod-socket = 666
pidfile      = /run/proj/uwsgi-proj.pid
vacuum       = true

#
# HTTP
#
#http = :8900

ソケット通信用のディレクトリを作成します。
HTTP通信の場合は不要です。
Debianの場合、「/var/run」は「/run」のシンボリックリンクなので「/run」で記述します。

sudo mkdir /run/proj
sudo chown www-data.www-data /run/proj
sudo chmod 777 /run/proj

Debianの場合、「/run」はtmpfsにマウントされているので、サーバを再起動すると「/run」以下のファイルは削除されてuWSGIの起動に失敗します。
そのため、tmpfs以外のディレクトリを指定するか、「/etc/tmpfiles.d」に設定ファイルを置いて、サーバの起動時にディレクトリを作成するようにします。
一度、OSを再起動してディレクトリが作成されるか確認します。

sudo vi /etc/tmpfiles.d/uwsgi-proj.conf

以下を入力して保存します。

d /run/proj 0777 www-data www-data

uwsgiコマンドのパスが、Djangoのプロジェクトディレクトリに作成した仮想環境であることを確認して、コマンドラインで起動します。

which uwsgi
     /home/www/wsgi/proj/.venv/bin/uwsgi

uwsgi --ini uwsgi.ini
     [uWSGI] getting INI configuration from uwsgi.ini

プロセスやログを確認して正常に動作したことを確認します。
確認後、CTRL-Cで終了します。
HTTP通信の場合は、以下のようにプロセスを停止します。

ps -ef | grep uwsgi
cat /home/www/wsgi/proj/uwsgi.log
uwsgi --stop /run/proj/uwsgi-proj.pid

systemdから自動起動するように設定ファイルを作成します。

sudo vi /etc/systemd/system/uwsgi-proj.service

設定ファイルは以下のようになります。

[Unit]
Description = uWSGI proj
After = syslog.target

[Service]
ExecStart = /home/www/wsgi/proj/.venv/bin/uwsgi --ini /home/www/wsgi/proj/uwsgi.ini
Restart = always
KillSignal = SIGQUIT
Type = notify
StandardError = syslog
NotifyAccess = all

[Install]
WantedBy = multi-user.target

systemdに登録して正常に起動することを確認します。

sudo systemctl enable uwsgi-proj
sudo systemctl is-enabled uwsgi-proj
sudo systemctl daemon-reload
sudo systemctl start uwsgi-proj

以下、操作コマンド。
sudo systemctl status uwsgi-proj
sudo systemctl stop uwsgi-proj
sudo systemctl restart uwsgi-proj

テスト

Webブラウザからアクセスしてテストします。

 http://aaa.bbb.ccc.ddd/proj

さいごに

仮想環境を作るごとにpipenvをインストールすることが分かっておらず、pipenvでライブラリをインストールするときにエラーが表示されて困りました。
「which pipenv」を実行して、pipenvのパスを確認するのが大切だと学びました。

Comments