DjangoでWebsocketを使うときにはChannelsというライブラリがよく使われています。これまではHerokuにデプロイをしてきましたが、HerokuとChannelsの相性が良くないのかすぐに接続が切れてしまうので、これからはAWS上で開発しようと思いました。公式ドキュメントを読んでもデプロイ方法がよく分からなかったのでメモしておきます。
AWS LightsailでUbuntu 18.04のインスタンスを立てたとして、SSHで入ってからHello, world!するところまでを見ていきます。
ライブラリのインストール
Daphneの起動を楽にするためにvenvを使います。(参考: Djangoのインストール · Django Girls Tutorial)
ssh ubuntu@xxx.xxx.xxx.xxx sudo apt update sudo apt install python3-venv python3 -m venv env source env/bin/activate
requirements.txt
に以下を記述します。
django~=3.0.5 channels~=2.4.0
pipをアップデートしてから必要なライブラリをインストールします。
python -m pip install --upgrade pip pip install -r requirements.txt
Hello, world!アプリの設定
Django プロジェクトを作成します。
django-admin startproject mysite cd mysite
基本的にはChannels公式ドキュメントのInstallationに従って設定します。簡単のために本番環境と開発環境の設定の分離などは無視します。
mysite/settings.py
を以下のように編集します。diffを示しています。
-ALLOWED_HOSTS = [] +ALLOWED_HOSTS = ['*'] # 本当は適切なホストを指定するべきだが簡単のため全て許可 (略) INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'channels', ] +ASGI_APPLICATION = "mysite.routing.application" + MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
mysite/routing.py
を以下の内容で作成します。
from channels.routing import ProtocolTypeRouter application = ProtocolTypeRouter({ # Empty for now (http->django views is added by default) })
mysite/urls.py
を以下の内容で作成します。
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), ]
mysite/views.py
を以下の内容で作成します。
from django.http import HttpResponse def index(request): return HttpResponse("Hello, world!")
ここまで来たら python manage.py runserver
を実行してエラーが出ないことだけ確認します。(サーバー上にあるのでこの時点ではブラウザで表示確認ができません)
NginxとSupervisorの設定
ここもChannels公式ドキュメントのDeployingに従って設定するだけなのですが、この通りにやっても動かなかったので以下のStackOverflowに従ってアレンジしました。
まずはNginxとSupervisorをインストールします。
sudo apt install nginx supervisor
mysite/asgi.py
を以下の内容で作成します。
""" ASGI entrypoint. Configures Django and then runs the application defined in the ASGI_APPLICATION setting. """ import os import django from channels.routing import get_default_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") django.setup() application = get_default_application()
/etc/supervisor/conf.d/asgi.conf
を以下の内容で作成します。
[fcgi-program:asgi] # TCP socket used by Nginx backend upstream socket=tcp://localhost:8000 # Directory where your site's project files are located directory=/home/ubuntu/mysite # Each process needs to have a separate socket file, so we use process_num # Make sure to update "mysite.asgi" to match your project name command=/home/ubuntu/env/bin/daphne --fd 0 --access-log - --proxy-headers mysite.asgi:application # Number of processes to startup, roughly the number of CPUs you have numprocs=4 # Give each process a unique name so they can be told apart process_name=asgi%(process_num)d # Automatically start and recover processes autostart=true autorestart=true # Choose where you want your log to go stdout_logfile=/var/log/asgi.log redirect_stderr=true
設定を読み込みます。
sudo supervisorctl reread sudo supervisorctl update
/etc/nginx/sites-available/default
を以下のように編集します。
upstream channels-backend { server localhost:8000; } ... server { ... location / { try_files $uri @proxy_to_app; } ... location @proxy_to_app { proxy_pass http://channels-backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } ... }
設定を読み込みます。
sudo service nginx reload
ブラウザのアドレス欄にこのサーバーのIPアドレスを入力すれば、Hello, world! と出力されたページを確認することができます。 次回はこのサーバーを使って簡単なWebsocketを使ったプログラムを書きます。