Debian 8でPostgres、Nginx、Gunicornを使用してDjangoを設定する方法
序章
Djangoは、PythonアプリケーションまたはWebサイトを立ち上げるのに役立つ強力なWebフレームワークです。 Djangoには、コードをローカルでテストするための簡略化された開発サーバーが含まれていますが、本番環境に少しでも関連する場合は、より安全で強力なWebサーバーが必要です。
このガイドでは、Djangoアプリケーションをサポートおよび提供するためにDebian8にいくつかのコンポーネントをインストールして構成する方法を示します。 デフォルトのSQLiteデータベースを使用する代わりに、PostgreSQLデータベースをセットアップします。 アプリケーションとインターフェイスするようにGunicornアプリケーションサーバーを構成します。 次に、GunicornにリバースプロキシするようにNginxを設定し、アプリを提供するためのセキュリティ機能とパフォーマンス機能にアクセスできるようにします。
前提条件と目標
このガイドを完了するには、sudo
権限が設定されたroot以外のユーザーがいる新しいDebian8サーバーインスタンスが必要です。 初期サーバーセットアップガイドを実行すると、これをセットアップする方法を学ぶことができます。
仮想環境内にDjangoをインストールします。 プロジェクトに固有の環境にDjangoをインストールすると、プロジェクトとその要件を個別に処理できるようになります。
データベースとアプリケーションを起動して実行したら、Gunicornアプリケーションサーバーをインストールして構成します。 これは、アプリケーションへのインターフェイスとして機能し、HTTPのクライアントリクエストをアプリケーションが処理できるPython呼び出しに変換します。 次に、Gunicornの前にNginxをセットアップして、その高性能接続処理メカニズムと実装が容易なセキュリティ機能を活用します。
始めましょう。
Debianリポジトリからパッケージをインストールします
プロセスを開始するには、Debianリポジトリから必要なすべてのアイテムをダウンロードしてインストールします。 Pythonパッケージマネージャーpip
を使用して、少し後で追加のコンポーネントをインストールします。
ローカルのapt
パッケージインデックスを更新してから、パッケージをダウンロードしてインストールする必要があります。 インストールするパッケージは、プロジェクトで使用するPythonのバージョンによって異なります。
Python 2 を使用している場合は、次のように入力します。
- sudo apt-get update
- sudo apt-get install python-pip python-dev libpq-dev postgresql postgresql-contrib nginx
Python 3 を使用している場合は、次のように入力します。
- sudo apt-get update
- sudo apt-get install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx
これにより、pip
、後でGunicornを構築するために必要なPython開発ファイル、Postgresデータベースシステムとそれと対話するために必要なライブラリ、およびNginxWebサーバーがインストールされます。
PostgreSQLデータベースとユーザーを作成する
すぐに参加して、Djangoアプリケーション用のデータベースとデータベースユーザーを作成します。
デフォルトでは、Postgresはローカル接続に「ピア認証」と呼ばれる認証スキームを使用します。 基本的に、これは、ユーザーのオペレーティングシステムのユーザー名が有効なPostgresユーザー名と一致する場合、そのユーザーはそれ以上の認証なしでログインできることを意味します。
Postgresのインストール中に、postgres
という名前のオペレーティングシステムユーザーが、postgres
PostgreSQL管理ユーザーに対応するように作成されました。 このユーザーを使用して管理タスクを実行する必要があります。 sudoを使用して、-u
オプションを使用してユーザー名を渡すことができます。
次のように入力して、インタラクティブなPostgresセッションにログインします。
- sudo -u postgres psql
要件を設定できるPostgreSQLプロンプトが表示されます。
まず、プロジェクトのデータベースを作成します。
ノート
すべてのPostgresステートメントはセミコロンで終了する必要があるため、問題を回避するために、コマンドがセミコロンで終了していることを確認してください。
- CREATE DATABASE myproject;
OutputCREATE DATABASE
次に、プロジェクトのデータベースユーザーを作成します。 安全なパスワードを選択してください。
- CREATE USER myprojectuser WITH PASSWORD 'password';
OutputCREATE ROLE
次に、作成したユーザーの接続パラメーターのいくつかを変更します。 これにより、データベース操作が高速化されるため、接続が確立されるたびに正しい値を照会して設定する必要がなくなります。
Djangoが期待するデフォルトのエンコーディングをUTF-8に設定しています。 また、デフォルトのトランザクション分離スキームを「読み取りコミット」に設定しています。これは、コミットされていないトランザクションからの読み取りをブロックします。 最後に、タイムゾーンを設定します。 デフォルトでは、DjangoプロジェクトはUTC
を使用するように設定されます。 これらはすべて、Djangoプロジェクト自体からの推奨事項です。
- 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';
OutputALTER ROLE
ALTER ROLE
ALTER ROLE
これで、新しいユーザーに新しいデータベースを管理するためのアクセス権を与えることができます。
- GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;
OutputGRANT
終了したら、次のように入力してPostgreSQLプロンプトを終了します。
- \q
シェルセッションに戻る必要があります。
プロジェクト用のPython仮想環境を作成します
データベースができたので、残りのプロジェクト要件の準備を始めることができます。 管理を容易にするために、Python要件を仮想環境内にインストールします。
これを行うには、最初にvirtualenv
コマンドにアクセスする必要があります。 これはpip
でインストールできます。
Python 2 を使用している場合は、次のように入力します。
- sudo pip install virtualenv
Python 3 を使用している場合は、次のように入力します。
- sudo pip3 install virtualenv
virtualenv
をインストールすると、プロジェクトの形成を開始できます。 プロジェクトファイルを保持できるディレクトリを作成して移動します。
- mkdir ~/myproject
- cd ~/myproject
プロジェクトディレクトリ内で、次のように入力してPython仮想環境を作成します。
- virtualenv venv
これにより、myproject
ディレクトリ内にvenv
というディレクトリが作成されます。 内部には、Pythonのローカルバージョンとpip
のローカルバージョンがインストールされます。 これを使用して、プロジェクト用に分離されたPython環境をインストールおよび構成できます。
プロジェクトのPython要件をインストールする前に、仮想環境をアクティブ化する必要があります。 次のように入力すると、次のように入力できます。
- source venv/bin/activate
プロンプトが変化して、Python仮想環境内で操作していることを示します。 (venv)user@host:~/myproject$
のようになります。
仮想環境をアクティブにして、Django、Gunicorn、およびpsycopg2
PostgreSQLアダプターをpip
のローカルインスタンスとともにインストールします。
ノート
使用しているPythonのバージョンに関係なく、仮想環境がアクティブ化されている場合は、pip
コマンドを使用する必要があります(pip3
ではありません)。
- pip install django gunicorn psycopg2
これらのコンポーネントは、グローバルパッケージから分離された仮想環境内にインストールされます。
新しいDjangoプロジェクトを作成して構成する
Pythonコンポーネントをインストールすると、実際のDjangoプロジェクトファイルを作成できます。
Djangoプロジェクトを作成する
すでにプロジェクトディレクトリがあるので、ここにファイルをインストールするようにDjangoに指示します。 これで、myproject
ディレクトリ内でDjangoプロジェクトを開始できます。 これにより、コード自体を保持する同じ名前の子ディレクトリが作成され、現在のディレクトリ内に管理スクリプトが作成されます。
注:コマンドの最後にドットを追加して、正しく設定されるようにしてください。 仮想環境ディレクトリを保持するための親プロジェクトディレクトリをすでに作成しているため、ドットを省略した場合に作成される追加のディレクトリレベルは必要ありません。
- django-admin.py startproject myproject .
現在のディレクトリ構造は次のようになります。
.
└── ./myproject/
├── manage.py
├── myproject/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── venv/
└── . . .
ご覧のとおり、manage.py
スクリプトを保持する親プロジェクトディレクトリ、内部プロジェクトディレクトリ、および前に作成したvenv
仮想環境ディレクトリがあります。
プロジェクト設定を調整する
新しく作成したプロジェクトファイルで最初に行うべきことは、設定を調整することです。 テキストエディタで設定ファイルを開きます。
- nano ~/myproject/myproject/settings.py
ALLOWED_HOSTS
ディレクティブを見つけることから始めます。 これは、Djangoインスタンスへの接続に使用できるアドレスまたはドメイン名のホワイトリストを定義します。 このリストにないHostヘッダーを持つ着信要求は、例外を発生させます。 Djangoでは、特定のクラスのセキュリティの脆弱性を防ぐためにこれを設定する必要があります。
角かっこ内に、Djangoサーバーに関連付けられているIPアドレスまたはドメイン名をリストします。 各項目は、引用符で、エントリをコンマで区切ってリストする必要があります。 ドメインおよびサブドメインの要求に応答する場合は、エントリの先頭にピリオドを追加します。 以下のスニペットには、エントリをフォーマットする正しい方法を示すために使用されるコメントアウトされた例がいくつかあります。
. . .
# 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', . . .]
次に、データベースアクセスを構成するセクションを見つけます。 DATABASES
で始まります。 ファイル内の構成はSQLiteデータベース用です。 プロジェクト用にPostgreSQLデータベースを作成済みなので、設定を調整する必要があります。
PostgreSQLデータベース情報で設定を変更します。 pip
とともにインストールしたpsycopg2
アダプターを使用するようにDjangoに指示します。 データベース名、データベースユーザー名、データベースユーザーのパスワードを指定してから、データベースがローカルコンピューター上にあることを指定する必要があります。 PORT
設定は空の文字列のままにしておくことができます。
. . .
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'myproject',
'USER': 'myprojectuser',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '',
}
}
. . .
次に、ファイルの一番下に移動し、静的ファイルを配置する場所を示す設定を追加します。 これは、Nginxがこれらのアイテムのリクエストを処理できるようにするために必要です。 次の行は、ベースプロジェクトディレクトリのstatic
というディレクトリにそれらを配置するようにDjangoに指示しています。
. . .
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
終了したら、ファイルを保存して閉じます。
プロジェクトの初期設定を完了する
これで、管理スクリプトを使用して、初期データベーススキーマをPostgreSQLデータベースに移行できます。
- cd ~/myproject
- ./manage.py makemigrations
- ./manage.py migrate
次のように入力して、プロジェクトの管理ユーザーを作成します。
- ./manage.py createsuperuser
ユーザー名を選択し、メールアドレスを入力し、パスワードを選択して確認する必要があります。
次のように入力して、構成したディレクトリの場所にすべての静的コンテンツを収集できます。
- ./manage.py collectstatic
操作を確認する必要があります。 静的ファイルは、プロジェクトディレクトリ内のstatic
というディレクトリに配置されます。
注:開発サーバーを試す前に、ファイアウォールでポートを開いていることを確認してください。
ufw
ファイアウォールを実行している場合は、次のように入力して適切なポートを開くことができます。
- sudo ufw allow 8000
iptables
ファイアウォールを実行している場合、必要な正確なコマンドは、現在のファイアウォール構成によって異なります。 ほとんどの構成の場合、次のコマンドが機能するはずです。
- sudo iptables -I INPUT -p tcp --dport 8000 -j ACCEPT
最後に、次のコマンドを使用してDjango開発サーバーを起動することにより、プロジェクトをテストできます。
- ./manage.py runserver 0.0.0.0:8000
Webブラウザーで、サーバーのドメイン名またはIPアドレスにアクセスし、その後に:8000
を続けます。
http://server_domain_or_IP:8000
デフォルトのDjangoインデックスページが表示されます。
アドレスバーのURLの末尾に/admin
を追加すると、createsuperuser
コマンドで作成した管理ユーザー名とパスワードの入力を求められます。
認証後、デフォルトのDjango管理インターフェースにアクセスできます。
探索が終了したら、ターミナルウィンドウでCTRL-Cを押して、開発サーバーをシャットダウンします。
プロジェクトにサービスを提供するGunicornの能力をテストする
仮想環境を離れる前に最後にやりたいことは、Gunicornをテストして、アプリケーションに対応できることを確認することです。 これは、次のように入力することで簡単に実行できます。
- cd ~/myproject
- gunicorn --bind 0.0.0.0:8000 myproject.wsgi:application
これにより、Django開発サーバーが実行されていたのと同じインターフェースでGunicornが起動します。 戻ってアプリをもう一度テストできます。
注: Gunicornはこれに関与する静的CSSコンテンツを認識していないため、管理インターフェースにはスタイルが適用されません。
Pythonのモジュール構文を使用して、アプリケーションへのエントリポイントであるDjangoのwsgi.py
ファイルへの相対ディレクトリパスを指定することにより、Gunicornにモジュールを渡しました。 このファイルの中には、application
という関数が定義されており、アプリケーションとの通信に使用されます。 WSGI仕様の詳細については、ここをクリックをクリックしてください。
テストが終了したら、ターミナルウィンドウでCTRL-Cを押してGunicornを停止します。
これで、Djangoアプリケーションの構成が完了しました。 次のように入力すると、仮想環境から戻ることができます。
- deactivate
仮想環境プレフィックスをシェルプロンプトから削除して、仮想環境にいないことを示す必要があります。
Gunicornsystemdサービスファイルを作成する
GunicornがDjangoアプリケーションと対話できることをテストしましたが、アプリケーションサーバーを起動および停止するためのより堅牢な方法を実装する必要があります。 これを実現するために、systemdサービスファイルを作成します。
テキストエディタでsudo
権限を持つGunicornのsystemdサービスファイルを作成して開きます。
- sudo nano /etc/systemd/system/gunicorn.service
[Unit]
セクションから始めます。このセクションは、メタデータと依存関係を指定するために使用されます。 ここにサービスの説明を入力し、ネットワークターゲットに到達した後にのみこれを開始するようにinitシステムに指示します。
[Unit]
Description=gunicorn daemon
After=network.target
次に、[Service]
セクションを開きます。 実行する処理を行うユーザーとグループを指定します。 プロセスは関連するすべてのファイルを所有しているため、通常のユーザーアカウントにプロセスの所有権を付与します。 NginxがGunicornと簡単に通信できるように、www-data
グループにグループ所有権を付与します。
次に、作業ディレクトリをマップし、サービスの開始に使用するコマンドを指定します。 この場合、仮想環境内にインストールされているGunicorn実行可能ファイルへのフルパスを指定する必要があります。 Nginxは同じコンピューターにインストールされているため、プロジェクトディレクトリ内のUnixソケットにバインドします。 これは、ネットワークポートを使用するよりも安全で高速です。 ここでは、オプションのGunicornの微調整を指定することもできます。 たとえば、この場合、3つのワーカープロセスを指定しました。
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
ExecStart=/home/sammy/myproject/venv/bin/gunicorn --workers 3 --bind unix:/home/sammy/myproject/myproject.sock myproject.wsgi:application
最後に、[Install]
セクションを追加します。 これにより、起動時にサービスを開始できるようにした場合に、このサービスを何にリンクするかがsystemdに通知されます。 このサービスは、通常のマルチユーザーシステムが稼働しているときに開始する必要があります。
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/myproject
ExecStart=/home/sammy/myproject/venv/bin/gunicorn --workers 3 --bind unix:/home/sammy/myproject/myproject.sock myproject.wsgi:application
[Install]
WantedBy=multi-user.target
これで、systemdサービスファイルが完成しました。 今すぐ保存して閉じます。
これで、作成したGunicornサービスを開始し、起動時に開始するように有効にすることができます。
- sudo systemctl start gunicorn
- sudo systemctl enable gunicorn
OutputCreated symlink from /etc/systemd/system/multi-user.target.wants/gunicorn.service to /etc/systemd/system/gunicorn.service.
次のように入力して、サービスのステータスを確認します。
- sudo systemctl status gunicorn
Output● gunicorn.service - gunicorn daemon
Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled)
Active: active (running) since Wed 2016-12-21 21:05:07 UTC; 49s ago
Main PID: 10154 (gunicorn)
CGroup: /system.slice/gunicorn.service
├─10154 /home/sammy/myproject/venv/bin/python3 /home/sammy/myproject/venv/bin/gunicorn --workers 3 --bind unix:/home/sammy/myproject/myproject.sock myproject.wsgi:application
├─10157 /home/sammy/myproject/venv/bin/python3 /home/sammy/myproject/venv/bin/gunicorn --workers 3 --bind unix:/home/sammy/myproject/myproject.sock myproject.wsgi:application
├─10158 /home/sammy/myproject/venv/bin/python3 /home/sammy/myproject/venv/bin/gunicorn --workers 3 --bind unix:/home/sammy/myproject/myproject.sock myproject.wsgi:application
└─10159 /home/sammy/myproject/venv/bin/python3 /home/sammy/myproject/venv/bin/gunicorn --workers 3 --bind unix:/home/sammy/myproject/myproject.sock myproject.wsgi:application
Dec 21 21:05:07 debian-512mb-nyc3-01 systemd[1]: Started gunicorn daemon.
Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10154] [INFO] Starting gunicorn 19.6.0
Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10154] [INFO] Listening at: unix:/home/sammy/myproject/myproject.sock (10154)
Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10154] [INFO] Using worker: sync
Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10157] [INFO] Booting worker with pid: 10157
Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10158] [INFO] Booting worker with pid: 10158
Dec 21 21:05:07 debian-512mb-nyc3-01 gunicorn[10154]: [2016-12-21 21:05:07 +0000] [10159] [INFO] Booting worker with pid: 10159
探すべき最も重要なことは、ユニットがアクティブであることです。
これは、ソケットファイルが作成されたことを確認する良い機会でもあります。 ~/myproject
ディレクトリの内容を一覧表示すると、Unixソケットファイルが表示されます。
- ls -l ~/myproject
Outputtotal 16
-rwxr-xr-x 1 sammy sammy 807 Dec 21 20:46 manage.py
drwxr-xr-x 3 sammy sammy 4096 Dec 21 20:54 myproject
srwxrwxrwx 1 sammy www-data 0 Dec 21 21:05 myproject.sock
drwxr-xr-x 3 sammy sammy 4096 Dec 21 20:54 static
drwxr-xr-x 5 sammy sammy 4096 Dec 21 20:41 venv
ご覧のとおり、ソケットはそこにあり、www-data
グループはグループの所有権を持っています。
NginxをGunicornへのプロキシパスに設定する
Gunicornがセットアップされたので、トラフィックをプロセスに渡すようにNginxを構成する必要があります。
Nginxのsites-available
ディレクトリに新しいサーバーブロックを作成して開くことから始めます。
- sudo nano /etc/nginx/sites-available/myproject
内部で、新しいサーバーブロックを開きます。 まず、このブロックが通常のポート80でリッスンし、サーバーのドメイン名またはIPアドレスに応答するように指定します。
server {
listen 80;
server_name server_domain_or_IP;
}
次に、ファビコンが見つからない場合にエラーを無視するようにNginxに指示できます。 また、~/myproject/static
ディレクトリで収集した静的アセットの場所も示します。 これらのファイルはすべて「/static」の標準URIプレフィックスを持っているため、これらのリクエストに一致するロケーションブロックを作成できます。
server {
listen 80;
server_name server_domain_or_IP;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/sammy/myproject;
}
}
最後に、他のすべてのリクエストに一致するlocation / {}
ブロックを作成します。 この場所の中に、Nginxインストールに含まれている標準のproxy_params
ファイルを含め、Gunicornプロセスが作成したソケットにトラフィックを渡します。
server {
listen 80;
server_name server_domain_or_IP;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/sammy/myproject;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/sammy/myproject/myproject.sock;
}
}
終了したら、ファイルを保存して閉じます。 これで、ファイルをsites-enabled
ディレクトリにリンクして有効にできます。
- sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
次のように入力して、構文エラーについてNginx構成をテストします。
- sudo nginx -t
Outputnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
エラーが報告されていない場合は、次のように入力してNginxを再起動してください。
- sudo systemctl restart nginx
注:ファイアウォールを有効にしている場合は、ファイアウォールを調整してポート8000を再度削除し、ポート80への通常のアクセスを許可します。
ufw
ファイアウォールを実行している場合は、次のように入力して適切なポートを開くことができます。
- sudo ufw delete allow 8000
- sudo ufw allow 'WWW'
iptables
ファイアウォールを実行している場合、必要な正確なコマンドは、現在のファイアウォール構成によって異なります。 ほとんどの構成の場合、次のコマンドが機能するはずです。
- sudo iptables -D INPUT -p tcp --dport 8000 -j ACCEPT
- sudo iptables -I INPUT -p tcp --dport 80 -j ACCEPT
これで、サーバーのドメインまたはIPアドレスに移動して、ポートを指定せずにアプリケーションを表示できるようになります。
ノート
Nginxを構成したら、次のステップはSSL/TLSを使用してサーバーへのトラフィックを保護することです。 これがないと、パスワードを含むすべての情報がプレーンテキストでネットワーク経由で送信されるため、これは重要です。
ドメイン名をお持ちの場合、トラフィックを保護するためにSSL証明書を取得する最も簡単な方法は、Let’sEncryptを使用することです。 このガイドに従って、Debian8でLet’sEncryptwithNginxを設定してください。
ドメイン名をお持ちでない場合でも、自己署名SSL証明書を使用して、テストと学習のためにサイトを保護できます。
結論
このガイドでは、独自の仮想環境でDjangoプロジェクトをセットアップしました。 Djangoがクライアントリクエストを処理できるように、クライアントリクエストを変換するようにGunicornを設定しました。 その後、クライアント接続を処理し、クライアントの要求に応じて正しいプロジェクトを提供するリバースプロキシとして機能するようにNginxを設定します。
Djangoは、多くの一般的な要素を提供することでプロジェクトとアプリケーションの作成を簡単にし、独自の要素に集中できるようにします。 この記事で説明する一般的なツールチェーンを活用することで、単一のサーバーから作成したアプリケーションを簡単に提供できます。