Ubuntu 18.04でPostgres、Nginx、Gunicornを使用してDjangoをセットアップする方法

前書き

Djangoは強力なWebフレームワークであり、PythonアプリケーションまたはWebサイトの開発を支援します。 Djangoには、ローカルでコードをテストするための簡素化された開発サーバーが含まれていますが、わずかに生産関連の場合でも、より安全で強力なWebサーバーが必要です。

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

前提条件と目標

このガイドを完了するには、基本的なファイアウォールを備えた新しいUbuntu 18.04サーバーインスタンスと、sudo権限が構成された非rootユーザーが必要です。 initial server setup guideを実行することで、これを設定する方法を学ぶことができます。

仮想環境にDjangoをインストールします。 プロジェクト固有の環境にDjangoをインストールすると、プロジェクトとその要件を個別に処理できます。

データベースとアプリケーションを起動して実行したら、Gunicornアプリケーションサーバーをインストールして構成します。 これは、アプリケーションへのインターフェイスとして機能し、クライアント要求をHTTPからアプリケーションが処理できるPython呼び出しに変換します。 次に、Gunicornの前にNginxをセットアップして、高性能な接続処理メカニズムと実装しやすいセキュリティ機能を活用します。

始めましょう。

Ubuntuリポジトリからのパッケージのインストール

プロセスを開始するには、Ubuntuリポジトリから必要なすべてのアイテムをダウンロードしてインストールします。 Pythonパッケージマネージャーpipを使用して、少し後で追加のコンポーネントをインストールします。

ローカルのaptパッケージインデックスを更新してから、パッケージをダウンロードしてインストールする必要があります。 インストールするパッケージは、プロジェクトで使用するPythonのバージョンによって異なります。

Python 3でDjangoを使用している場合は、次のように入力します。

sudo apt update
sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl

Django 1.11は、Python 2をサポートするDjangoの最後のリリースです。 新しいプロジェクトを開始する場合は、Python 3を選択することを強くお勧めします。 それでもPython 2を使用する必要がある場合は、次のように入力します。

sudo apt update
sudo apt install python-pip python-dev libpq-dev postgresql postgresql-contrib nginx curl

これにより、pip、後でGunicornをビルドするために必要なPython開発ファイル、Postgresデータベースシステムとそれと対話するために必要なライブラリ、およびNginxWebサーバーがインストールされます。

PostgreSQLデータベースとユーザーの作成

Djangoアプリケーションのデータベースとデータベースユーザーをすぐに作成します。

デフォルトでは、Postgresはローカル接続に「ピア認証」と呼ばれる認証スキームを使用します。 基本的に、これはユーザーのオペレーティングシステムのユーザー名が有効なPostgresユーザー名と一致する場合、そのユーザーはそれ以上認証なしでログインできることを意味します。

Postgresのインストール中に、postgres PostgreSQL管理ユーザーに対応するpostgresという名前のオペレーティングシステムユーザーが作成されました。 このユーザーを使用して管理タスクを実行する必要があります。 sudoを使用して、-uオプションを使用してユーザー名を渡すことができます。

次のように入力して、インタラクティブなPostgresセッションにログインします。

sudo -u postgres psql

要件を設定できるPostgreSQLプロンプトが表示されます。

まず、プロジェクトのデータベースを作成します。

CREATE DATABASE myproject;

[.note]#Note:すべてのPostgresステートメントはセミコロンで終了する必要があるため、問題が発生している場合は、コマンドがセミコロンで終了していることを確認してください。

次に、プロジェクトのデータベースユーザーを作成します。 安全なパスワードを選択してください:

CREATE USER myprojectuser WITH PASSWORD 'password';

その後、作成したユーザーの接続パラメーターのいくつかを変更します。 これにより、データベース操作が高速化されるため、接続が確立されるたびに正しい値を照会および設定する必要がなくなります。

Djangoが期待するデフォルトのエンコーディングをUTF-8に設定しています。 また、デフォルトのトランザクション分離スキームを「コミット済み読み取り」に設定しています。これは、コミットされていないトランザクションからの読み取りをブロックします。 最後に、タイムゾーンを設定しています。 デフォルトでは、DjangoプロジェクトはUTCを使用するように設定されます。 これらはすべてthe Django project itselfからの推奨事項です。

ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
ALTER ROLE myprojectuser SET timezone TO 'UTC';

これで、新しいユーザーに新しいデータベースを管理するアクセス権を与えることができます。

GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;

終了したら、次のように入力してPostgreSQLプロンプトを終了します。

\q

Djangoがデータベース情報に接続して管理できるように、Postgresが設定されました。

プロジェクト用のPython仮想環境の作成

データベースができたので、残りのプロジェクト要件の準備を開始できます。 管理を容易にするために、仮想環境にPython要件をインストールします。

これを行うには、最初にvirtualenvコマンドにアクセスする必要があります。 これはpipでインストールできます。

Python 3を使用している場合は、pipをアップグレードし、次のように入力してパッケージをインストールします。

sudo -H pip3 install --upgrade pip
sudo -H pip3 install virtualenv

Python 2を使用している場合は、pipをアップグレードし、次のように入力してパッケージをインストールします。

sudo -H pip install --upgrade pip
sudo -H pip install virtualenv

virtualenvがインストールされたら、プロジェクトの形成を開始できます。 プロジェクトファイルを保存できるディレクトリを作成して移動します。

mkdir ~/myprojectdir
cd ~/myprojectdir

プロジェクトディレクトリ内で、次のように入力してPython仮想環境を作成します。

virtualenv myprojectenv

これにより、myprojectdirディレクトリ内にmyprojectenvというディレクトリが作成されます。 内部では、Pythonのローカルバージョンとpipのローカルバージョンがインストールされます。 これを使用して、プロジェクトの分離されたPython環境をインストールおよび構成できます。

プロジェクトのPython要件をインストールする前に、仮想環境をアクティブ化する必要があります。 次のように入力して、それを行うことができます。

source myprojectenv/bin/activate

プロンプトが変わり、Python仮想環境内で操作していることを示す必要があります。 (myprojectenv)[email protected]:~/myprojectdir$のようになります。

仮想環境をアクティブにして、Django、Gunicorn、およびpipのローカルインスタンスを使用したpsycopg2PostgreSQLアダプターをインストールします。

[.note]#Note:仮想環境がアクティブ化されている場合(プロンプトの前に(myprojectenv)がある場合)、Pythonを使用している場合でも、pip3ではなくpipを使用します3.3。 ツールの仮想環境のコピーには、Pythonのバージョンに関係なく、常にpipという名前が付けられます。

pip install django gunicorn psycopg2-binary

これで、Djangoプロジェクトを開始するために必要なすべてのソフトウェアが準備できました。

新しいDjangoプロジェクトの作成と構成

Pythonコンポーネントをインストールすると、実際のDjangoプロジェクトファイルを作成できます。

Djangoプロジェクトの作成

既にプロジェクトディレクトリがあるので、ここにファイルをインストールするようDjangoに指示します。 通常の実際のコードで第2レベルのディレクトリを作成し、このディレクトリに管理スクリプトを配置します。 これの鍵は、Djangoが現在のディレクトリに関連した決定を行うことを許可する代わりに、ディレクトリを明示的に定義することです。

django-admin.py startproject myproject ~/myprojectdir

この時点で、プロジェクトディレクトリ(この場合は~/myprojectdir)には次の内容が含まれているはずです。

  • ~/myprojectdir/manage.py:Djangoプロジェクト管理スクリプト。

  • ~/myprojectdir/myproject/:Djangoプロジェクトパッケージ。 これには、__init__.pysettings.pyurls.py、およびwsgi.pyファイルが含まれている必要があります。

  • ~/myprojectdir/myprojectenv/:前に作成した仮想環境ディレクトリ。

プロジェクト設定の調整

新しく作成したプロジェクトファイルで最初に行うべきことは、設定を調整することです。 テキストエディターで設定ファイルを開きます。

nano ~/myprojectdir/myproject/settings.py

ALLOWED_HOSTSディレクティブを見つけることから始めます。 これは、Djangoインスタンスへの接続に使用されるサーバーのアドレスまたはドメイン名のリストを定義します。 このリストにないHostヘッダーを持つ着信要求は、例外を発生させます。 Djangoでは、特定のクラスのセキュリティ脆弱性を防ぐために、これを設定する必要があります。

角括弧内に、Djangoサーバーに関連付けられているIPアドレスまたはドメイン名をリストします。 各項目は、エントリをカンマで区切って引用符で囲んでください。 ドメイン全体とサブドメインのリクエストを希望する場合は、エントリの先頭にピリオドを追加します。 以下のスニペットには、デモンストレーションに使用されるコメントアウトされた例がいくつかあります。

[.note]#Note:ローカルのNginxインスタンスを介して接続をプロキシするため、オプションの1つとして必ずlocalhostを含めてください。

~/myprojectdir/myproject/settings.py

. . .
# The simplest case: just add the domain name(s) and IP addresses of your Django server
# ALLOWED_HOSTS = [ 'example.com', '203.0.113.5']
# To respond to 'example.com' and any subdomains, start the domain with a dot
# ALLOWED_HOSTS = ['.example.com', '203.0.113.5']
ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . ., 'localhost']

次に、データベースアクセスを構成するセクションを見つけます。 DATABASESで始まります。 ファイル内の構成は、SQLiteデータベース用です。 プロジェクト用にPostgreSQLデータベースをすでに作成しているため、設定を調整する必要があります。

PostgreSQLデータベース情報を使用して設定を変更します。 pipでインストールしたpsycopg2アダプターを使用するようにDjangoに指示します。 データベース名、データベースユーザー名、データベースユーザーのパスワードを指定し、データベースがローカルコンピューターにあることを指定する必要があります。 PORT設定は空の文字列のままにしておくことができます。

~/myprojectdir/myproject/settings.py

. . .

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'myproject',
        'USER': 'myprojectuser',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '',
    }
}

. . .

次に、ファイルの一番下まで移動し、静的ファイルを配置する場所を示す設定を追加します。 これは、Nginxがこれらのアイテムのリクエストを処理できるようにするために必要です。 次の行は、ベースプロジェクトディレクトリのstaticというディレクトリにそれらを配置するようにDjangoに指示しています。

~/myprojectdir/myproject/settings.py

. . .

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

完了したら、ファイルを保存して閉じます。

初期プロジェクト設定の完了

これで、管理スクリプトを使用して初期データベーススキーマをPostgreSQLデータベースに移行できます。

~/myprojectdir/manage.py makemigrations
~/myprojectdir/manage.py migrate

次を入力して、プロジェクトの管理ユーザーを作成します。

~/myprojectdir/manage.py createsuperuser

ユーザー名を選択し、メールアドレスを入力し、パスワードを選択して確認する必要があります。

次のように入力して、すべての静的コンテンツを構成したディレクトリの場所に収集できます。

~/myprojectdir/manage.py collectstatic

操作を確認する必要があります。 静的ファイルは、プロジェクトディレクトリ内のstaticというディレクトリに配置されます。

サーバーの初期セットアップガイドに従った場合は、サーバーを保護するUFWファイアウォールが必要です。 開発用サーバーをテストするには、使用するポートへのアクセスを許可する必要があります。

次のように入力して、ポート8000​​の例外を作成します。

sudo ufw allow 8000

最後に、次のコマンドでDjango開発サーバーを起動して、プロジェクトをテストできます。

~/myprojectdir/manage.py runserver 0.0.0.0:8000

Webブラウザーで、サーバーのドメイン名またはIPアドレスにアクセスし、その後に:8000を続けます。

http://server_domain_or_IP:8000

デフォルトのDjangoインデックスページが表示されます。

Django index page

アドレスバーのURLの末尾に/adminを追加すると、createsuperuserコマンドで作成した管理ユーザー名とパスワードの入力を求められます。

Django admin login

認証後、デフォルトのDjango管理インターフェースにアクセスできます。

Django admin interface

探索が終了したら、ターミナルウィンドウでCTRL-Cを押して、開発サーバーをシャットダウンします。

Gunicornのプロジェクト提供能力のテスト

仮想環境を離れる前にやりたい最後のことは、Gunicornをテストして、アプリケーションを提供できることを確認することです。 これを行うには、プロジェクトディレクトリに入り、gunicornを使用してプロジェクトのWSGIモジュールをロードします。

cd ~/myprojectdir
gunicorn --bind 0.0.0.0:8000 myproject.wsgi

これにより、Django開発サーバーが実行されていたのと同じインターフェースでGunicornが起動します。 戻ってアプリをもう一度テストできます。

[.note]#Note: Gunicornはこれに関与する静的CSSコンテンツを見つける方法を知らないため、管理インターフェイスにはスタイルが適用されません。

Pythonのモジュール構文を使用して、アプリケーションへのエントリポイントであるDjangoのwsgi.pyファイルへの相対ディレクトリパスを指定することにより、Gunicornにモジュールを渡しました。 このファイル内には、アプリケーションとの通信に使用されるapplicationという関数が定義されています。 WSGI仕様の詳細については、hereをクリックしてください。

テストが終了したら、ターミナルウィンドウでCTRL-Cを押して、Gunicornを停止します。

これで、Djangoアプリケーションの構成が完了しました。 次のように入力して、仮想環境からバックアウトできます。

deactivate

プロンプトの仮想環境インジケータは削除されます。

Gunicorn用のsystemdソケットおよびサービスファイルの作成

GunicornがDjangoアプリケーションとやり取りできることをテストしましたが、アプリケーションサーバーを起動および停止するより堅牢な方法を実装する必要があります。 これを実現するために、systemdサービスとソケットファイルを作成します。

Gunicornソケットは起動時に作成され、接続をリッスンします。 接続が発生すると、systemdはGunicornプロセスを自動的に開始して接続を処理します。

sudo権限を持つGunicornのsystemdソケットファイルを作成して開くことから始めます。

sudo nano /etc/systemd/system/gunicorn.socket

内部では、ソケットを説明するための[Unit]セクション、ソケットの場所を定義するための[Socket]セクション、およびソケットが適切なタイミングで作成されることを確認するための[Install]セクションを作成します。

/etc/systemd/system/gunicorn.socket

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

完了したら、ファイルを保存して閉じます。

次に、テキストエディタでsudo権限を持つGunicornのsystemdサービスファイルを作成して開きます。 サービスファイル名は、拡張子を除き、ソケットファイル名と一致する必要があります。

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

メタデータと依存関係を指定するために使用される[Unit]セクションから始めます。 ここにサービスの説明を入力し、ネットワーキングターゲットに到達した後にのみ開始するようにinitシステムに指示します。 私たちのサービスはソケットファイルのソケットに依存しているため、その関係を示すためにRequiresディレクティブを含める必要があります。

/etc/systemd/system/gunicorn.service

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

次に、[Service]セクションを開きます。 実行するために処理するユーザーとグループを指定します。 関連するすべてのファイルを所有しているため、通常のユーザーアカウントにプロセスの所有権を付与します。 NginxがGunicornと簡単に通信できるように、www-dataグループにグループの所有権を付与します。

次に、作業ディレクトリをマップし、サービスを開始するために使用するコマンドを指定します。 この場合、仮想環境内にインストールされているGunicorn実行可能ファイルへのフルパスを指定する必要があります。 プロセスがNginxと通信できるように、/runディレクトリ内に作成したUnixソケットにプロセスをバインドします。 journaldプロセスがGunicornログを収集できるように、すべてのデータを標準出力に記録します。 ここで、オプションのGunicorn調整を指定することもできます。 たとえば、この場合、3つのワーカープロセスを指定しました。

/etc/systemd/system/gunicorn.service

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

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myprojectdir
ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          myproject.wsgi:application

最後に、[Install]セクションを追加します。 これにより、起動時に起動できるようにした場合、このサービスをリンクする対象がsystemdに指示されます。 通常のマルチユーザーシステムが稼働しているときにこのサービスを開始する必要があります。

/etc/systemd/system/gunicorn.service

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

[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myprojectdir
ExecStart=/home/sammy/myprojectdir/myprojectenv/bin/gunicorn \
          --access-logfile - \
          --workers 3 \
          --bind unix:/run/gunicorn.sock \
          myproject.wsgi:application

[Install]
WantedBy=multi-user.target

これで、systemdサービスファイルが完成しました。 今すぐ保存して閉じます。

これで、Gunicornソケットを開始して有効にすることができます。 これにより、現在および起動時に/run/gunicorn.sockにソケットファイルが作成されます。 そのソケットに接続が確立されると、systemdは自動的にgunicorn.serviceを開始してそれを処理します。

sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket

ソケットファイルを確認することで、操作が成功したことを確認できます。

Gunicornソケットファイルの確認

プロセスのステータスを確認して、プロセスを開始できたかどうかを確認します。

sudo systemctl status gunicorn.socket

次に、/runディレクトリ内にgunicorn.sockファイルが存在するかどうかを確認します。

file /run/gunicorn.sock
Output/run/gunicorn.sock: socket

systemctl statusコマンドがエラーの発生を示した場合、またはディレクトリにgunicorn.sockファイルが見つからない場合は、Gunicornソケットを正しく作成できなかったことを示しています。 次を入力して、Gunicornソケットのログを確認します。

sudo journalctl -u gunicorn.socket

続行する前に、/etc/systemd/system/gunicorn.socketファイルをもう一度確認して、問題を修正してください。

ソケットアクティベーションのテスト

現在、gunicorn.socketユニットのみを起動した場合、ソケットはまだ接続を受信して​​いないため、gunicorn.serviceはまだアクティブになりません。 これを確認するには、次のように入力します。

sudo systemctl status gunicorn
Output● gunicorn.service - gunicorn daemon
   Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled)
   Active: inactive (dead)

ソケットのアクティブ化メカニズムをテストするには、次のように入力して、curlを介してソケットに接続を送信します。

curl --unix-socket /run/gunicorn.sock localhost

端末にアプリケーションからのHTML出力が表示されます。 これは、Gunicornが開始され、Djangoアプリケーションを提供できたことを示しています。 次のように入力して、Gunicornサービスが実行されていることを確認できます。

sudo systemctl status gunicorn
Output● gunicorn.service - gunicorn daemon
   Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled)
   Active: active (running) since Mon 2018-07-09 20:00:40 UTC; 4s ago
 Main PID: 1157 (gunicorn)
    Tasks: 4 (limit: 1153)
   CGroup: /system.slice/gunicorn.service
           ├─1157 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application
           ├─1178 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application
           ├─1180 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application
           └─1181 /home/sammy/myprojectdir/myprojectenv/bin/python3 /home/sammy/myprojectdir/myprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock myproject.wsgi:application

Jul 09 20:00:40 django1 systemd[1]: Started gunicorn daemon.
Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1157] [INFO] Starting gunicorn 19.9.0
Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1157] [INFO] Listening at: unix:/run/gunicorn.sock (1157)
Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1157] [INFO] Using worker: sync
Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1178] [INFO] Booting worker with pid: 1178
Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1180] [INFO] Booting worker with pid: 1180
Jul 09 20:00:40 django1 gunicorn[1157]: [2018-07-09 20:00:40 +0000] [1181] [INFO] Booting worker with pid: 1181
Jul 09 20:00:41 django1 gunicorn[1157]:  - - [09/Jul/2018:20:00:41 +0000] "GET / HTTP/1.1" 200 16348 "-" "curl/7.58.0"

curlからの出力またはsystemctl statusの出力が問題が発生したことを示している場合は、ログで詳細を確認してください。

sudo journalctl -u gunicorn

/etc/systemd/system/gunicorn.serviceファイルに問題がないか確認してください。 /etc/systemd/system/gunicorn.serviceファイルに変更を加えた場合は、デーモンをリロードしてサービス定義を再読み取りし、次のように入力してGunicornプロセスを再起動します。

sudo systemctl daemon-reload
sudo systemctl restart gunicorn

続行する前に、上記の問題をトラブルシューティングしてください。

NunicornをGunicornにプロキシパスするように構成する

Gunicornがセットアップされたので、プロセスにトラフィックを渡すようにNginxを構成する必要があります。

Nginxのsites-availableディレクトリに新しいサーバーブロックを作成して開くことから始めます。

sudo nano /etc/nginx/sites-available/myproject

内部で、新しいサーバーブロックを開きます。 まず、このブロックが通常のポート80でリッスンし、サーバーのドメイン名またはIPアドレスに応答するように指定することから始めます。

/etc/nginx/sites-available/myproject

server {
    listen 80;
    server_name server_domain_or_IP;
}

次に、ファビコンを見つける際の問題を無視するようにNginxに指示します。 また、~/myprojectdir/staticディレクトリで収集した静的アセットの場所も示します。 これらのファイルにはすべて「/ static」の標準URIプレフィックスが付いているため、これらの要求に一致する場所ブロックを作成できます。

/etc/nginx/sites-available/myproject

server {
    listen 80;
    server_name server_domain_or_IP;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/sammy/myprojectdir;
    }
}

最後に、他のすべてのリクエストに一致するlocation / {}ブロックを作成します。 この場所の中に、Nginxインストールに含まれている標準のproxy_paramsファイルを含めてから、トラフィックをGunicornソケットに直接渡します。

/etc/nginx/sites-available/myproject

server {
    listen 80;
    server_name server_domain_or_IP;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/sammy/myprojectdir;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/run/gunicorn.sock;
    }
}

完了したら、ファイルを保存して閉じます。 これで、ファイルをsites-enabledディレクトリにリンクして有効にできます。

sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled

次のように入力して、構文エラーのNginx設定をテストします。

sudo nginx -t

エラーが報告されていない場合は、次のように入力してNginxを再起動します。

sudo systemctl restart nginx

最後に、ポート80で通常のトラフィックに対してファイアウォールを開く必要があります。 開発サーバーにアクセスする必要がなくなったため、ポート8000​​を開くルールも削除できます。

sudo ufw delete allow 8000
sudo ufw allow 'Nginx Full'

これで、サーバーのドメインまたはIPアドレスにアクセスして、アプリケーションを表示できるようになります。

[。注意]##

Note: Nginxを構成したら、次のステップはSSL / TLSを使用してサーバーへのトラフィックを保護することです。 これは重要です。これがないと、パスワードを含むすべての情報がプレーンテキストでネットワーク経由で送信されます。

ドメイン名がある場合、SSL証明書を取得してトラフィックを保護する最も簡単な方法は、Let’s Encryptを使用することです。 this guideに従って、Ubuntu18.04でLet’s Encrypt withNginxを設定します。 このガイドで作成したNginxサーバーブロックを使用した手順に従います。

ドメイン名をお持ちでない場合でも、self-signed SSL certificateを使用してテストと学習のためにサイトを保護できます。 繰り返しますが、このチュートリアルで作成したNginxサーバーブロックを使用してプロセスに従います。

NginxとGunicornのトラブルシューティング

この最後の手順でアプリケーションが表示されない場合は、インストールのトラブルシューティングを行う必要があります。

NginxはDjangoアプリケーションの代わりにデフォルトページを表示しています

Nginxがアプリケーションにプロキシする代わりにデフォルトのページを表示する場合は、通常、サーバーのIPアドレスまたはドメイン名を指すように/etc/nginx/sites-available/myprojectファイル内のserver_nameを調整する必要があることを意味します。

Nginxはserver_nameを使用して、リクエストへの応答に使用するサーバーブロックを決定します。 デフォルトのNginxページが表示されている場合は、Nginxがリクエストをサーバーブロックに明示的に一致させることができなかったため、/etc/nginx/sites-available/defaultで定義されたデフォルトブロックにフォールバックしています。

プロジェクトのサーバーブロックのserver_nameは、選択するデフォルトのサーバーブロックのserver_nameよりも具体的である必要があります。

NginxがDjangoアプリケーションの代わりに502 Bad Gatewayエラーを表示している

502エラーは、Nginxがリクエストを正常にプロキシできないことを示します。 さまざまな構成の問題が502エラーで表されるため、適切にトラブルシューティングするにはより多くの情報が必要です。

詳細情報を検索する主な場所は、Nginxのエラーログです。 通常、これにより、プロキシイベント中に問題が発生した条件がわかります。 次のように入力して、Nginxエラーログに従います。

sudo tail -F /var/log/nginx/error.log

次に、ブラウザで別のリクエストを行って、新しいエラーを生成します(ページを更新してみてください)。 ログに新しいエラーメッセージが書き込まれます。 メッセージを見ると、問題を絞り込むのに役立つはずです。

次のメッセージの一部が表示される場合があります。

unix:/run/gunicorn.sockへのconnect()が失敗しました(2:そのようなファイルまたはディレクトリはありません)

これは、Nginxが指定された場所でgunicorn.sockファイルを見つけることができなかったことを示しています。 /etc/nginx/sites-available/myprojectファイル内で定義されたproxy_passの場所を、gunicorn.socket systemdユニットによって生成されたgunicorn.sockファイルの実際の場所と比較する必要があります。

/runディレクトリ内にgunicorn.sockファイルが見つからない場合は、通常、systemdソケットファイルで作成できなかったことを意味します。 section on checking for the Gunicorn socket fileに戻り、Gunicornのトラブルシューティング手順を実行します。

UNIXへのconnect():/ run / gunicorn.sockが失敗しました(13:アクセスが拒否されました)

これは、権限の問題により、NginxがGunicornソケットに接続できなかったことを示しています。 これは、sudoユーザーの代わりにrootユーザーを使用してプロシージャを実行した場合に発生する可能性があります。 systemdはGunicornソケットファイルを作成できますが、Nginxはアクセスできません。

これは、ルートディレクトリ(/)とgunicorn.sockファイルの間の任意の時点でアクセス許可が制限されている場合に発生する可能性があります。 ソケットファイルへの絶対パスをnameiコマンドに渡すことにより、ソケットファイルとその各親ディレクトリのアクセス許可と所有権の値を確認できます。

namei -l /run/gunicorn.sock
Outputf: /run/gunicorn.sock
drwxr-xr-x root root /
drwxr-xr-x root root run
srw-rw-rw- root root gunicorn.sock

出力には、各ディレクトリコンポーネントの権限が表示されます。 許可(最初の列)、所有者(2番目の列)、グループ所有者(3番目の列)を調べることで、ソケットファイルへのアクセスが許可されているタイプを把握できます。

上記の例では、ソケットファイルとソケットファイルにつながる各ディレクトリには、ワールド読み取りおよび実行のアクセス許可があります(ディレクトリのアクセス許可列は、---ではなくr-xで終わります)。 Nginxプロセスは、ソケットに正常にアクセスできるはずです。

ソケットにつながるディレクトリのいずれかがワールドの読み取りおよび実行の許可を持っていない場合、Nginxは、ワールドの読み取りおよび実行の許可を許可するか、Nginxが属するグループにグループ所有権が付与されることなく、ソケットにアクセスできませんの。

Djangoが表示しています:「サーバーに接続できませんでした:接続が拒否されました」

Webブラウザでアプリケーションの一部にアクセスしようとしたときにDjangoから表示される可能性のあるメッセージの1つは次のとおりです。

OperationalError at /admin/login/
could not connect to server: Connection refused
    Is the server running on host "localhost" (127.0.0.1) and accepting
    TCP/IP connections on port 5432?

これは、DjangoがPostgresデータベースに接続できないことを示しています。 次のように入力して、Postgresインスタンスが実行されていることを確認します。

sudo systemctl status postgresql

起動していない場合は、次のように入力して起動し、起動時に自動的に起動するように設定できます(まだ起動していない場合)。

sudo systemctl start postgresql
sudo systemctl enable postgresql

それでも問題が解決しない場合は、~/myprojectdir/myproject/settings.pyファイルで定義されているデータベース設定が正しいことを確認してください。

さらなるトラブルシューティング

追加のトラブルシューティングのために、ログは根本原因を絞り込むのに役立ちます。 それぞれを順番に確認し、問題のある領域を示すメッセージを探します。

次のログが役立つ場合があります。

  • 次のように入力して、Nginxプロセスログを確認します:sudo journalctl -u nginx

  • 次のように入力して、Nginxアクセスログを確認します:sudo less /var/log/nginx/access.log

  • 次のように入力して、Nginxエラーログを確認します:sudo less /var/log/nginx/error.log

  • 次のように入力して、Gunicornアプリケーションログを確認します。sudo journalctl -u gunicorn

  • 次のように入力して、Gunicornソケットログを確認します。sudo journalctl -u gunicorn.socket

構成またはアプリケーションを更新する場合、変更を調整するためにプロセスを再起動する必要があります。

Djangoアプリケーションを更新する場合、次のように入力してGunicornプロセスを再起動し、変更を反映できます。

sudo systemctl restart gunicorn

Gunicornソケットまたはサービスファイルを変更する場合は、デーモンをリロードし、次を入力してプロセスを再起動します。

sudo systemctl daemon-reload
sudo systemctl restart gunicorn.socket gunicorn.service

Nginxサーバーブロックの構成を変更する場合は、構成をテストしてから、次のように入力してNginxをテストします。

sudo nginx -t && sudo systemctl restart nginx

これらのコマンドは、構成を調整するときに変更を取得するのに役立ちます。

結論

このガイドでは、独自の仮想環境でDjangoプロジェクトを設定しました。 Djangoがクライアントリクエストを処理できるように、クライアントリクエストを変換するようにGunicornを設定しました。 その後、Nginxを設定してリバースプロキシとして機能し、クライアント接続を処理し、クライアントのリクエストに応じて正しいプロジェクトを提供します。

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

Related