序章

Djangoは、PythonアプリケーションまたはWebサイトを立ち上げるのに役立つ強力なWebフレームワークです。 Djangoには、コードをローカルでテストするための簡略化された開発サーバーが含まれていますが、本番環境に少しでも関連する場合は、より安全で強力なWebサーバーが必要です。

このガイドでは、Djangoアプリケーションをサポートおよび提供するためにCentOS7にいくつかのコンポーネントをインストールおよび構成する方法を示します。 アプリケーションとインターフェイスするようにuWSGIアプリケーションコンテナサーバーを構成します。 次に、uWSGIにリバースプロキシするようにNginxを設定し、アプリを提供するためのセキュリティ機能とパフォーマンス機能にアクセスできるようにします。

前提条件と目標

このガイドを完了するには、sudo権限が設定されたroot以外のユーザーがいる新しいCentOS7サーバーインスタンスが必要です。 初期サーバーセットアップガイドを実行すると、これをセットアップする方法を学ぶことができます。

Djangoを2つの異なる仮想環境にインストールします。 これにより、プロジェクトとその要件を個別に処理できるようになります。 マルチプロジェクト環境で手順を実行できるように、2つのサンプルプロジェクトを作成します。

アプリケーションを入手したら、uWSGIアプリケーションサーバーをインストールして構成します。 これは、アプリケーションへのインターフェイスとして機能し、HTTPを使用してクライアントリクエストをアプリケーションが処理できるPython呼び出しに変換します。 次に、uWSGIの前にNginxをセットアップして、その高性能接続処理メカニズムと実装が容易なセキュリティ機能を利用します。

始めましょう。

VirtualEnvとVirtualEnvWrapperをインストールして構成します

Djangoプロジェクトを独自の仮想環境にインストールして、それぞれの要件を分離します。 これを行うために、Python仮想環境を作成できるvirtualenvと、virtualenvワークフローにいくつかの使いやすさを追加するvirtualenvwrapperをインストールします。

Pythonパッケージマネージャーであるpipを使用して、これらのコンポーネントの両方をインストールします。 pipを取得するには、最初にEPELリポジトリを有効にする必要があります。 これは、次のように入力することで簡単に実行できます。

sudo yum install epel-release

EPELを有効にしたら、次のように入力してpipをインストールできます。

sudo yum install python-pip

pipがインストールされたので、次のように入力してvirtualenvvirtualenvwrapperをグローバルにインストールできます。

sudo pip install virtualenv virtualenvwrapper

これらのコンポーネントがインストールされたら、virtualenvwrapperスクリプトで動作するために必要な情報を使用してシェルを構成できます。 仮想環境はすべて、簡単にアクセスできるように、Envというホームフォルダ内のディレクトリに配置されます。 これは、WORKON_HOMEと呼ばれる環境変数を介して構成されます。 これをシェル初期化スクリプトに追加して、仮想環境ラッパースクリプトを入手できます。

シェル初期化スクリプトに適切な行を追加するには、次のコマンドを実行する必要があります。

echo "export WORKON_HOME=~/Env" >> ~/.bashrc
echo "source /usr/bin/virtualenvwrapper.sh" >> ~/.bashrc

次に、シェル初期化スクリプトを入手して、現在のセッションでこの機能を使用できるようにします。

source ~/.bashrc

これで、仮想環境情報を保持するEnvというディレクトリがホームフォルダに作成されます。

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

仮想環境ツールができたので、2つの仮想環境を作成し、それぞれにDjangoをインストールして、2つのプロジェクトを開始します。

最初のプロジェクトを作成する

virtualenvwrapperスクリプトで使用できるコマンドを使用すると、仮想環境を簡単に作成できます。

次のように入力して、最初のサイトまたはプロジェクトの名前で最初の仮想環境を作成します。

mkvirtualenv firstsite

これにより、仮想環境が作成され、その中にPythonとpipがインストールされ、環境がアクティブ化されます。 プロンプトが変わり、新しい仮想環境内で操作していることを示します。 (firstsite)user@hostname:~$のようになります。 括弧内の値は、仮想環境の名前です。 pipを介してインストールされたソフトウェアはすべて、グローバルシステムではなく、仮想環境にインストールされるようになります。 これにより、プロジェクトごとにパッケージを分離できます。

最初のステップは、Django自体をインストールすることです。 これは仮想環境にローカルにインストールするため、sudoなしでpipを使用できます。

pip install django

Djangoをインストールしたら、次のように入力して最初のサンプルプロジェクトを作成できます。

cd ~
django-admin.py startproject firstsite

これにより、ホームディレクトリ内にfirstsiteというディレクトリが作成されます。 この中には、プロジェクトのさまざまな側面を処理するために使用される管理スクリプトと、実際のプロジェクトコードを格納するために使用される同じ名前の別のディレクトリがあります。

サンプルプロジェクトの最小要件の設定を開始できるように、第1レベルのディレクトリに移動します。

cd ~/firstsite

データベースを移行して、プロジェクトで使用するSQLiteデータベースを初期化することから始めます。 必要に応じて、アプリケーションの代替データベースを設定できますが、これはこのガイドの範囲外です。

./manage.py migrate

これで、プロジェクトディレクトリにdb.sqlite3というデータベースファイルが作成されます。 これで、次のように入力して管理ユーザーを作成できます。

./manage.py createsuperuser

ユーザー名を選択し、連絡先の電子メールアドレスを指定してから、パスワードを選択して確認する必要があります。

次に、テキストエディタでプロジェクトの設定ファイルを開きます。

nano firstsite/settings.py

サイトにサービスを提供するようにNginxを設定するため、サイトの静的アセットを保持するディレクトリを構成する必要があります。 これにより、Nginxがこれらを直接提供できるようになり、パフォーマンスにプラスの影響があります。 これらをプロジェクトのベースディレクトリのstaticというディレクトリに配置するようにDjangoに指示します。 この動作を構成するには、ファイルの最後に次の行を追加します。

STATIC_ROOT = os.path.join(BASE_DIR, "static/")

終了したら、ファイルを保存して閉じます。 次に、サイトの静的要素を収集し、次のように入力してそのディレクトリ内に配置します。

./manage.py collectstatic

「yes」と入力して、アクションを確認し、静的コンテンツを収集できます。 プロジェクトディレクトリにstaticという新しいディレクトリが作成されます。

これらすべてが終わったら、開発サーバーを一時的に起動してプロジェクトをテストできます。 タイプ:

./manage.py runserver 0.0.0.0:8080

これにより、ポート8080で開発サーバーが起動します。 サーバーのドメイン名またはIPアドレスにアクセスし、続いてブラウザで8080にアクセスします。

http://server_domain_or_IP:8080

次のようなページが表示されます。

Django sample site

ブラウザのアドレスバーのURLの末尾に/adminを追加すると、管理者ログインページに移動します。

Django admin login

createsuperuserコマンドで選択した管理ログイン資格情報を使用して、サーバーにログインします。 これで、管理インターフェースにアクセスできるようになります。

Django admin interface

この機能をテストした後、ターミナルでCTRL-Cを入力して、開発サーバーを停止します。 これで、2番目のプロジェクトに進むことができます。

2番目のプロジェクトを作成する

2番目のプロジェクトは、最初のプロジェクトとまったく同じ方法で作成されます。 このセクションの説明は、あなたがすでにこれをどのように完了したかを見て、簡略化します。

ホームディレクトリに戻り、新しいプロジェクト用の2番目の仮想環境を作成します。 アクティベートされたら、この新しい環境内にDjangoをインストールします。

cd ~
mkvirtualenv secondsite
pip install django

新しい環境が作成され、がに変更され、以前の仮想環境が残ります。 このDjangoインスタンスは、構成した他のインスタンスとは完全に分離されています。 これにより、それらを個別に管理し、必要に応じてカスタマイズできます。

2番目のプロジェクトを作成し、プロジェクトディレクトリに移動します。

django-admin.py startproject secondsite
cd ~/secondsite

データベースを初期化し、管理ユーザーを作成します。

./manage.py migrate
./manage.py createsuperuser

設定ファイルを開きます。

nano secondsite/settings.py

前のプロジェクトで行ったように、静的ファイルの場所を追加します。

STATIC_ROOT = os.path.join(BASE_DIR, "static/")

ファイルを保存して閉じます。 次に、次のように入力して、静的要素をそのディレクトリに収集します。

./manage.py collectstatic

最後に、開発サーバーを起動してサイトをテストします。

./manage.py runserver 0.0.0.0:8080

次の通常のサイトを確認する必要があります。

http://server_domain_or_IP:8080

また、管理サイトにログインします。

http://server_domain_or_IP:8080/admin

すべてが期待どおりに機能していることを確認したら、ターミナルでCTRL-Cを入力して、開発サーバーを停止します。

仮想環境からのバックアウト

これでガイドのDjangoの部分が終了したので、2番目の仮想環境を非アクティブ化できます。

deactivate

いずれかのDjangoサイトで再度作業する必要がある場合は、それぞれの環境を再アクティブ化する必要があります。 workonコマンドを使用してこれを行うことができます。

workon firstsite

または:

workon secondsite

繰り返しますが、サイトでの作業が終了したら非アクティブ化します。

deactivate

uWSGIアプリケーションサーバーのセットアップ

2つのDjangoプロジェクトをセットアップして準備ができたので、uWSGIを構成できます。 uWSGIは、WSGIと呼ばれる標準インターフェイスを介してアプリケーションと通信できるアプリケーションサーバーです。 これについて詳しくは、Ubuntu14.04でのuWSGIとNginxのセットアップに関するガイドのこのセクションをお読みください。

uWSGIのインストール

上記のリンク先のガイドとは異なり、このチュートリアルでは、uWSGIをグローバルにインストールします。 これにより、複数のDjangoプロジェクトを処理する際の摩擦が少なくなります。 uWSGIをインストールする前に、ソフトウェアが依存するPython開発ファイルが必要です。 コンパイラも必要です。 yumを使用して、これらの両方を取得できます。

sudo yum install python-devel gcc

開発ファイルが利用可能になったので、次のように入力して、pipを介してuWSGIをグローバルにインストールできます。

sudo pip install uwsgi

このアプリケーションサーバーは、いずれかのサイトの情報を渡すことですばやくテストできます。 たとえば、次のように入力することで、最初のプロジェクトを提供するように指示できます。

uwsgi --http :8080 --home /home/user/Env/firstsite --chdir /home/user/firstsite -w firstsite.wsgi

ここでは、~/Envディレクトリにある仮想環境を使用し、プロジェクトのディレクトリに移動し、内部のfirstsite内に保存されているwsgi.pyファイルを使用するようにuWSGIに指示しました。 ]ファイルを提供するディレクトリ。 デモンストレーションでは、ポート8080でHTTPを提供するように指示しました。 ブラウザでサーバーのドメイン名またはIPアドレスに移動し、続いて:8080に移動すると、サイトが再び表示されます(/adminインターフェイスの静的要素はまだ機能しません)。 この機能のテストが終了したら、ターミナルにCTRL-Cと入力します。

構成ファイルの作成

コマンドラインからuWSGIを実行することはテストには役立ちますが、実際の展開には特に役立ちません。 代わりに、uWSGIを「エンペラーモード」で実行します。これにより、マスタープロセスは、構成ファイルのセットを指定して、個別のアプリケーションを自動的に管理できます。

構成ファイルを保持するディレクトリを作成します。 これはグローバルプロセスであるため、構成ファイルを保存するために/etc/uwsgi/sitesというディレクトリを作成します。 作成後、ディレクトリに移動します。

sudo mkdir -p /etc/uwsgi/sites
cd /etc/uwsgi/sites

このディレクトリに、構成ファイルを配置します。 提供しているプロジェクトごとに構成ファイルが必要です。 uWSGIプロセスは、さまざまな形式の構成ファイルを受け取ることができますが、単純さのために.iniファイルを使用します。

最初のプロジェクトのファイルを作成し、テキストエディタで開きます。

sudo nano firstsite.ini

内部では、[uwsgi]セクションヘッダーから始める必要があります。 すべての情報はこのヘッダーの下に表示されます。 また、変数を使用して、構成ファイルをより再利用しやすくします。 ヘッダーの後に、最初のプロジェクトの名前を使用してprojectという変数を設定します。 プロジェクトファイルを所有する通常のユーザー名で別の変数を設定します。 ユーザー名を使用してユーザーのホームディレクトリへのパスを確立するbaseという変数を追加します。

[uwsgi]
project = firstsite
username = user
base = /home/%(username)

次に、プロジェクトを正しく処理するようにuWSGIを構成する必要があります。 chdirオプションを設定して、ルートプロジェクトディレクトリに変更する必要があります。 %(variable_name)構文を使用して、前に設定したホームディレクトリとプロジェクト名の設定を組み合わせることができます。 これは、構成が読み取られるときに変数の値に置き換えられます。

同様の方法で、プロジェクトの仮想環境を示します。 モジュールを設定することで、プロジェクトとのインターフェース方法を正確に示すことができます(プロジェクトディレクトリ内のwsgi.pyファイルから呼び出し可能な「アプリケーション」をインポートすることにより)。 これらのアイテムの構成は次のようになります。

[uwsgi]
project = firstsite
username = user
base = /home/%(username)

chdir = %(base)/%(project)
home = %(base)/Env/%(project)
module = %(project).wsgi:application

5人のワーカーでマスタープロセスを作成したいと思います。 これを追加することでこれを行うことができます:

[uwsgi]
project = firstsite
username = user
base = /home/%(username)

chdir = %(base)/%(project)
home = %(base)/Env/%(project)
module = %(project).wsgi:application

master = true
processes = 5

次に、uWSGIが接続をリッスンする方法を指定する必要があります。 uWSGIのテストでは、HTTPとネットワークポートを使用しました。 ただし、リバースプロキシとしてNginxを使用するため、より適切なオプションがあります。

ネットワークポートを使用する代わりに、すべてのコンポーネントが単一のサーバーで動作しているため、Unixソケットを使用できます。 これはより安全で、より良いパフォーマンスを提供します。 このソケットはHTTPを使用しませんが、代わりにuWSGIのuwsgiプロトコルを実装します。これは、他のサーバーと通信するために設計された高速バイナリプロトコルです。 Nginxはuwsgiプロトコルを使用してネイティブにプロキシできるため、これが最善の選択です。

プロセスを実行するユーザーを設定する必要があります。 また、Webサーバーに書き込みアクセスを許可するため、ソケットのアクセス許可と所有権も変更します。 ソケット自体は、uWSGIとNginxの両方がアクセスできる/run/uwsgiディレクトリ(このディレクトリを少し作成します)内に配置されます。 vacuumオプションを設定して、サービスが停止したときにソケットファイルが自動的にクリーンアップされるようにします。

[uwsgi]
project = firstsite
username = user
base = /home/%(username)

chdir = %(base)/%(project)
home = %(base)/Env/%(project)
module = %(project).wsgi:application

master = true
processes = 5

uid = %(username)
socket = /run/uwsgi/%(project).sock
chown-socket = %(username):nginx
chmod-socket = 660
vacuum = true

これで、最初のプロジェクトのuWSGI構成が完了しました。 ファイルを保存して閉じます。

変数を使用してファイルを設定する利点は、再利用が非常に簡単になることです。 最初のプロジェクトの構成ファイルをコピーして、2番目の構成ファイルのベースとして使用します。

sudo cp /etc/uwsgi/sites/firstsite.ini /etc/uwsgi/sites/secondsite.ini

テキストエディタで2番目の構成ファイルを開きます。

sudo nano /etc/uwsgi/sites/secondsite.ini

2番目のプロジェクトで機能させるには、このファイルの1つの値を変更するだけで済みます。 project変数を、2番目のプロジェクトで使用した名前に変更します。

[uwsgi]
project = firstsite
username = user
base = /home/%(username)

chdir = %(base)/%(project)
home = %(base)/Env/%(project)
module = %(project).wsgi:application

master = true
processes = 5

uid = %(username)
socket = /run/uwsgi/%(project).sock
chown-socket = %(username):nginx
chmod-socket = 660
vacuum = true

終了したら、ファイルを保存して閉じます。 2番目のプロジェクトは今すぐ準備ができているはずです。

uWSGIのSystemdユニットファイルを作成する

これで、Djangoプロジェクトを提供するために必要な構成ファイルができましたが、プロセスはまだ自動化されていません。 次に、起動時にuWSGIを自動的に起動するSystemdユニットファイルを作成します。

ユーザーが作成したユニットファイルが保存されている/etc/systemd/systemディレクトリにユニットファイルを作成します。 ファイルをuwsgi.serviceと呼びます。

sudo nano /etc/systemd/system/uwsgi.service

メタデータを指定するために使用される[Unit]セクションから始めます。 ここにサービスの説明を簡単に記載します。

[Unit]
Description=uWSGI Emperor service

次に、[Service]セクションを開きます。 ExecStartPreディレクティブを使用して、サーバーを実行するために必要な部分を設定します。 これにより、/run/uwsgiディレクトリが作成され、通常のユーザーがNginxグループをグループ所有者として所有していることが確認されます。 -pフラグが設定されたmkdirchownコマンドは、すでに存在していても正常に戻ります。 これが私たちが望んでいることです。

ExecStartディレクティブで指定された実際の開始コマンドでは、uwsgi実行可能ファイルを指します。 「Emperormode」で実行するように指示し、/etc/uwsgi/sitesで見つかったファイルを使用して複数のアプリケーションを管理できるようにします。 また、Systemdがプロセスを正しく管理するために必要な要素を追加します。 これらは、uWSGIドキュメントここから取得されます。

[Unit]
Description=uWSGI Emperor service

[Service]
ExecStartPre=/usr/bin/bash -c 'mkdir -p /run/uwsgi; chown user:nginx /run/uwsgi'
ExecStart=/usr/bin/uwsgi --emperor /etc/uwsgi/sites
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all

ここで、[Install]セクションを追加するだけです。 これにより、サービスを自動的に開始するタイミングを指定できます。 サービスをマルチユーザーシステムの状態に結び付けます。 システムが複数のユーザー向けに設定されている場合(通常の動作状態)、当社のサービスがアクティブになります。

[Unit]
Description=uWSGI Emperor service

[Service]
ExecStartPre=/usr/bin/bash -c 'mkdir -p /run/uwsgi; chown user:nginx /run/uwsgi'
ExecStart=/usr/bin/uwsgi --emperor /etc/uwsgi/sites
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all

[Install]
WantedBy=multi-user.target

これが終了したら、ファイルを保存して閉じます。

nginxユーザーが利用可能であることに依存しているため、この時点でサービスを正常に開始することはできません。 Nginxがインストールされるまで、uWSGIサービスの開始を待つ必要があります。

Nginxをリバースプロキシとしてインストールおよび構成する

uWSGIを構成して準備ができたら、Nginxをリバースプロキシとしてインストールして構成できます。 これは、yumを使用してダウンロードおよびインストールできます。

sudo yum install nginx

Nginxがインストールされたら、先に進んでメイン構成ファイルを編集できます。

sudo nano /etc/nginx/nginx.conf

このファイル内で、既存のサーバーブロックの隣に、サイトごとに追加のサーバーブロックを作成します。

http {

    . . .

    include /etc/nginx/conf.d/*.conf;

    server {
    }

    server {
    }

    server {
        listen 80 default_server;
        server_name localhost;

        . . .

作成したブロックは、uWSGIサイトの構成を保持します。 ここで、最初のサーバーブロックで必要なディレクティブについて説明します。

まず、サーバーブロックに応答するポート番号とドメイン名を指示する必要があります。 各サイトのドメイン名があると想定します。

server {
    listen 80;
    server_name firstsite.com www.firstsite.com;
}

次に、ファビコンの欠落について心配する必要がないことをNginxに通知します。 次に、これらのファイルが要求されたときに、最初のサイトの静的アセットが収集されたディレクトリを指定します。 Nginxは、それらをそのディレクトリからクライアントに直接渡すことができます。

server {
    listen 80;
    server_name firstsite.com www.firstsite.com;

    location = favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/user/firstsite;
    }
}

次に、すべての追加クエリをuWSGIに直接渡すキャッチオールロケーションブロックを作成します。 /etc/nginx/uwsgi_paramsファイルにあるuwsgiパラメータを含め、uWSGIサーバーが設定するソケットにトラフィックを渡します。

server {
    listen 80;
    server_name firstsite.com www.firstsite.com;

    location = favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/user/firstsite;
    }

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/run/uwsgi/firstsite.sock;
    }
}

これで、最初のサーバーブロックが完成しました。

他のサイトの2番目のサーバーブロックはほぼ同じです。 開始するために作成したサーバーブロックをコピーして貼り付けることができます。 サイトが応答するドメイン名、サイトの静的ファイルの場所、およびサイトのソケットファイルを変更する必要があります。

server {
    listen 80;
    server_name secondsite.com www.secondsite.com;

    location = favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/user/secondsite;
    }

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/run/uwsgi/secondsite.sock;
    }
}

この手順が終了したら、ファイルを保存して閉じます。

Nginxファイルの構文をチェックして、間違いがないことを確認します。

sudo nginx -t

エラーが報告されない場合、ファイルは良好な状態です。

サイトを正しく機能させるために完了しなければならない追加のタスクが1つあります。 Nginxは静的ファイルを直接処理しているため、適切なディレクトリにアクセスする必要があります。 ホームディレクトリの実行可能アクセス許可を与える必要があります。これは、ホームディレクトリに欠けている唯一のアクセス許可ビットです。

これを行う最も安全な方法は、Nginxユーザーを独自のユーザーグループに追加することです。 次に、ホームディレクトリのグループ所有者に実行可能ファイルのアクセス許可を追加して、Nginxがファイルを提供するのに十分なアクセス権を与えることができます。

sudo usermod -a -G user nginx
chmod 710 /home/user

これで、NginxサーバーとuWSGIプロセスを開始できます。

sudo systemctl start nginx
sudo systemctl start uwsgi

これで、それぞれのドメイン名に移動して、2つのプロジェクトにアクセスできるようになります。 パブリックインターフェイスと管理インターフェイスの両方が期待どおりに機能するはずです。

これがうまくいけば、次のように入力して、起動時に両方のサービスを自動的に開始できるようにすることができます。

sudo systemctl enable nginx
sudo systemctl enable uwsgi

結論

このガイドでは、それぞれ独自の仮想環境に2つのDjangoプロジェクトを設定しました。 それぞれに構成された仮想環境を使用して、各プロジェクトに個別にサービスを提供するようにuWSGIを構成しました。 その後、クライアント接続を処理し、クライアントの要求に応じて正しいプロジェクトを提供するリバースプロキシとして機能するようにNginxを設定します。

Djangoは、多くの一般的な要素を提供することでプロジェクトとアプリケーションの作成を簡単にし、独自の要素に集中できるようにします。 この記事で説明する一般的なツールチェーンを活用することで、単一のサーバーから作成したアプリケーションを簡単に提供できます。