Ubuntu 16.04でECS上でPostgreSQLとGunicornを使ってDjangoをセットアップ

ここでは、Ubuntu 16.04を使用した**Alibaba Cloud ECSインスタンス**にPostgreSQLデータベースと**Gunicorn**を使用した**Django**をインストールして設定します。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-16-04_594319)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

#前提条件
1、Alibaba Cloud Ubuntu 16.04インスタンス。
2、固定 IP アドレスが設定されています。
3、インスタンスにルートパスワードが設定されています。

#ECSインスタンスを起動
まず、[Alibaba Cloud ECS Console](https://ecs.console.aliyun.com/?spm=a2c65.11461447.0.0.7dd84f51itlGPJ)にログインします。新しい[ECSインスタンス](https://www.alibabacloud.com/help/doc-detail/25424.htm?spm=a2c65.11461447.0.0.7dd84f51itlGPJ)を作成し、少なくとも2GBのRAMを搭載したオペレーティングシステムとしてUbuntu 16.04を選択します。[ECSインスタンス](https://www.alibabacloud.com/help/doc-detail/25434.htm?spm=a2c65.11461447.0.0.7dd84f51itlGPJ)に接続し、rootユーザーとしてログインします。

Ubuntu 16.04インスタンスにログインしたら、以下のコマンドを実行して、ベースシステムを最新の利用可能なパッケージで更新します。

```
apt-get update -y
```

#必要なパッケージのインストール
始める前に、Nginx, PostgreSQL と Python のパッケージをシステムにインストールする必要があります。以下のコマンドですべてインストールできます。

```
apt-get install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx -y
```

すべてのパッケージがインストールされたら PostgreSQLデータベースの設定に進むことができます。

#PostgreSQLの設定
次に、Djangoアプリケーション用のPostgreSQLデータベースとユーザを作成する必要があります。

まず、以下のコマンドを実行してPostgreSQLの対話セッションにログインします。

```
sudo -u postgres psql
```

次に、以下のコマンドを使用して、DjangoプロジェクトのPostgreSQLデータベースとユーザを作成します。


```
postgres=# CREATE DATABASE testproject;
postgres=# CREATE USER testuser WITH PASSWORD 'password'; 
```

次に、デフォルトのエンコーディングをUTF-8に設定し、デフォルトのトランザクション分離スキームを "read committed "に設定し、以下のコマンドでタイムゾーンをUTCに設定します。

```
postgres=# ALTER ROLE testuser SET client_encoding TO 'utf8';
postgres=# ALTER ROLE testuser SET default_transaction_isolation TO 'read committed';
postgres=# ALTER ROLE testuser SET timezone TO 'UTC';
```

次に、データベースにすべての権限を付与し、以下のコマンドでPostgreSQLセッションを終了します。

```
postgres=# GRANT ALL PRIVILEGES ON DATABASE testproject TO testuser;
postgres=#  \q
```

#Pythonの仮想環境を作成する
次に、プロジェクト用のPython仮想環境を作成する必要があります。仮想環境内にPythonで必要なパッケージをインストールすることで行うことができます。

まずはpipをアップグレードし、以下のコマンドで仮想環境をインストールします。

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

次に、プロジェクトのディレクトリを作成します。

```
mkdir ~/testproject
cd ~/testproject
```

次に、以下のコマンドを実行してPythonの仮想環境を作成します。

```
virtualenv testprojectenv
```

上記のコマンドでtestprojectディレクトリの下にtestprojectenvディレクトリを作成し、ローカル版のPythonとローカル版のpipをインストールします。

次に、プロジェクトに必要なパッケージをすべてインストールする必要があります。

まず、以下のコマンドで仮想環境を起動します。

```
source testprojectenv/bin/activate
```

仮想環境を有効化したら、以下のコマンドでDjango、Gunicorn、psycopg2 PostgreSQLアダプタをインストールします。

```
(testprojectenv) root@mail:~/testproject# pip install django gunicorn psycopg2
```

出力:

```
Installing collected packages: pytz, django, gunicorn, psycopg2
Successfully installed django-2.1.1 gunicorn-19.9.0 psycopg2-2.7.5 pytz-2018.5
```

#新しいDjangoプロジェクトを設定する
次に、プロジェクトディレクトリ内にレコードをインストールするようにDjangoに指示する必要があります。これは以下のコマンドで行うことができます。

```
(testprojectenv) root@mail:~/testproject# django-admin.py startproject testproject ~/testproject
```

次に、settings.pyファイルでサーバのIPアドレス、データベースのユーザ名、パスワードを定義する必要があります。

```
(testprojectenv) root@mail:~/testproject# nano /root/testproject/testproject/settings.py
```

以下の変更を行います。

```
ALLOWED_HOSTS = ['192.168.43.192']

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

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

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

次に、初期データベーススキーマをPostgreSQLデータベースに移行する必要があります。これは、以下のスクリプトを実行することで行うことができます。


```
(testprojectenv) root@mail:~/testproject# ~/testproject/manage.py makemigrations
(testprojectenv) root@mail:~/testproject# ~/testproject/manage.py migrate
```

次に、以下のコマンドを実行して、プロジェクトの管理ユーザーを作成します。

```
(testprojectenv) root@mail:~/testproject# ~/testproject/manage.py createsuperuser
```

出力:

```
Username (leave blank to use 'root'): 
Email address: admin@example.com
Password: 
Password (again): 
Superuser created successfully.
```

次に、以下のコマンドを実行して、設定したディレクトリの場所に静的コンテンツをすべて収集します。

```
(testprojectenv) root@mail:~/testproject# ~/testproject/manage.py collectstatic
```

これで、以下のコマンドでDjango開発サーバーを起動してプロジェクトを開始することができます。

```
(testprojectenv) root@mail:~/testproject# ~/testproject/manage.py runserver 0.0.0.0.0:8000
```

サーバーが正常に起動したら 以下のような出力が表示されるはずです。

システムチェックの実行中...

```
System check identified no issues (0 silenced).
September 10, 2018 - 15:06:07
Django version 2.1.1, using settings 'testproject.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
```

さて、ウェブブラウザを開き、URL [http://your-server-ip:8000](http://your-server-ip:8000/?spm=a2c65.11461447.0.0.7dd84f51ha1Xoz) と入力します。すると、以下のようにDjangoのインデックスページにリダイレクトされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/1290add3-1f04-2221-d696-f686a7c094bf.png)


また、URL http://your-server-ip:8000/admin をブラウザに入力して、Django の管理者インターフェースにアクセスすることもできます。以下のように、以前に作成した管理者用のユーザー名とパスワードを入力するように促されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/4abdcdf6-6d86-c6a6-9b70-2f2250941ecf.png)


ユーザー名とパスワードを入力したら、ログインボタンをクリックします。以下のようにDjangoの管理画面にリダイレクトされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/eb668dbe-d75c-f3aa-4739-a55240f14535.png)


ここで、ターミナルウィンドウでCTRL+Cを押して開発サーバーをシャットダウンします。

Gunicornがアプリケーションにサービスを提供できるかどうかをテストするためにGunicornをテストしたい場合、以下のコマンドでプロジェクトのWSGIモジュールをロードします。

```
(testprojectenv) root@mail:~/testproject# gunicorn --bind 0.0.0.0:8000 testproject.wsgi
```

上記のコマンドを実行すると、Django開発サーバーが稼働していたのと同じインターフェイスでGunicornが起動します。URL [http://your-server-ip:8000](http://your-server-ip:8000/?spm=a2c65.11461447.0.0.7dd84f51ha1Xoz) にアクセスしてテストすることができます。

テストが完了したら、ターミナルでCTRL+Cを押してGunicornを停止させます。

次に、以下のコマンドを実行して仮想環境を非アクティブ化します。

```
(testprojectenv) root@mail:~/testproject# deactivate
```

#Gunicorn用のSystemdサービスファイルを作成する
次に、Gunicorn用のsystemdサービスファイルを作成します。これで、アプリケーションサーバーを簡単に起動したり停止したりすることができます。以下のようなファイルを作成すればOKです。

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

以下の行を追加します。

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

[Service]
User=root
Group=www-data
WorkingDirectory=/root/testproject
ExecStart=/root/testproject/testprojectenv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/root/testproject/testproject.sock testproject.wsgi:application

[Install]
WantedBy=multi-user.target
```

ファイルを保存して閉じます。その後、以下のコマンドでGunicornサービスを開始し、起動時に開始できるようにします。

```
systemctl start gunicorn
systemctl enable gunicorn
```

以下のコマンドでGunicornの状態を確認できます。

```
systemctl status gunicorn
```

出力します。

```
  gunicorn.service - gunicorn daemon
   Loaded: loaded (/etc/systemd/system/gunicorn.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2018-09-10 20:58:14 IST; 10s ago
 Main PID: 2377 (gunicorn)
   CGroup: /system.slice/gunicorn.service
           ├─2377 /root/testproject/testprojectenv/bin/python3 /root/testproject/testprojectenv/bin/gunicorn --access-logfile - --workers 3 --b
           ├─2384 /root/testproject/testprojectenv/bin/python3 /root/testproject/testprojectenv/bin/gunicorn --access-logfile - --workers 3 --b
           ├─2385 /root/testproject/testprojectenv/bin/python3 /root/testproject/testprojectenv/bin/gunicorn --access-logfile - --workers 3 --b
           └─2386 /root/testproject/testprojectenv/bin/python3 /root/testproject/testprojectenv/bin/gunicorn --access-logfile - --workers 3 --b

Sep 10 20:58:14 mail.example.com systemd[1]: Started gunicorn daemon.
Sep 10 20:58:14 mail.example.com gunicorn[2377]: [2018-09-10 20:58:14 +0530] [2377] [INFO] Starting gunicorn 19.9.0
Sep 10 20:58:14 mail.example.com gunicorn[2377]: [2018-09-10 20:58:14 +0530] [2377] [INFO] Listening at: unix:/root/testproject/testproject.soc
Sep 10 20:58:14 mail.example.com gunicorn[2377]: [2018-09-10 20:58:14 +0530] [2377] [INFO] Using worker: sync
Sep 10 20:58:14 mail.example.com gunicorn[2377]: [2018-09-10 20:58:14 +0530] [2384] [INFO] Booting worker with pid: 2384
Sep 10 20:58:15 mail.example.com gunicorn[2377]: [2018-09-10 20:58:15 +0530] [2385] [INFO] Booting worker with pid: 2385
Sep 10 20:58:15 mail.example.com gunicorn[2377]: [2018-09-10 20:58:15 +0530] [2386] [INFO] Booting worker with pid: 2386
```

#NginxをGunicornにProxy Passするように設定する
これで Gunicorn が設定され、動作するようになりました。etc/nginx/sites-available/ディレクトリ内に新しいNginx設定ファイルを作成します。

```
nano /etc/nginx/sites-available/gunicorn
```

以下の行を追加します。

```
server {
    listen 80;
    server_name 192.168.43.192;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /root/testproject;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/root/testproject/testproject.sock;
    }
}
```


ファイルを保存して閉じます。その後、シンボリックリンクを作成してNginxバーチャルホストを有効にします。

```
ln -s /etc/nginx/sites-available/gunicorn /etc/nginx/sites-enabled/
```

次に、以下のコマンドでNginxに設定ミスがないかテストします。

```
nginx -t
```

出力されます。

```
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
```

最後に、以下のコマンドを実行してNginxを再起動します。

```
systemctl restart nginx
```


これで、Nginxがプロセスにトラフィックを渡すように設定されました。テストするには、ウェブブラウザを開き、URL [http://your-server-ip](http://your-server-ip./?spm=a2c65.11461447.0.0.7dd84f51ha1Xoz) と入力してください。すると、以下のページのようにアプリケーションにリダイレクトされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/e55e8222-887a-b343-3bcd-9d9d9590dfd1.png)


*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*