知識の枝

"All is well"

Django ASGI仕様のアプリをデプロイ②

約157日前 2021年12月11日13:50
デジタル
ホームページ Django Python SSL 仮想環境 Git

改訂履歴


2021/12/11 投稿

1. 本記事について


本記事は 「Django ASGI仕様のアプリをデプロイ」 の後編です。

全体構成
  1. 開発環境でアプリを作る(ここまで終わっている前提)
  2. サーバー契約
  3. ubuntuの初期設定
  4. ssh接続
  5. 最新版のPythonを入れる
  6. データベース(postgresql)を入れる
  7. nginxの動作確認
  8. Pythonの仮想環境を作る
  9. Django etc..をインストール
  10. gunicornの設定
  11. 静的ファイルの配信設定
  12. ドメインの取得&設定
  13. 常時SSL化
  14. 動作確認
のうち、8~14部分の解説記事です。

前半の記事をご覧になりたい方は下記のリンクからどうぞ。
リンク
Django ASGI仕様のアプリをデプロイ①


それでは早速、後半の解説を始めます。



2. デプロイ


2.1 - Pythonの仮想環境を作る


前半の記事でインストールしたPython3.9.5をベースに仮想環境を作ります。

まずはvirtualenvをインストールします。
$ sudo -H pip3 install virtualenv


続いて仮想環境(ここでは仮想環境名をvenvとします)を作成。
先にユーザーのホームディレクトリに移動しておきます。
$ cd /home/ユーザー名
$ virtualenv venv
created virtual environment CPython3.9.5.final.0-64 in 1187ms
creator CPython3Posix(dest=/home/ユーザー名/venv, clear=False, no_vcs_ignore=False, global=False)
...
ホームディレクトリ /home/ユーザー名 に仮想環境 "venv" が作成されました。

作った仮想環境に入ります。
$ source venv/bin/activate
(venv) $
(venv)が左側に表示されていますね。venvという仮想環境内にいることを示しています。

この仮想環境の中にDjangoやアプリの動作に必要なライブラリ等をインストールしていきます。


2.2 - Django etc..をインストール


PythonにDjangoをインストールしなければ作ったアプリは動きませんので、まずはDjangoをインストールします。

仮想環境内
(venv) $ pip3 install django
インストールできました。

インストールされたものを確認します。
(venv) $ pip3 freeze
asgiref==3.4.1
Django==3.2.9
pytz==2021.3
sqlparse==0.4.2
Django3.2.9がインストールされました。

アプリの開発環境をバージョンを揃えたい場合は、バージョン指定してインストールしましょう。
(venv) $ pip3 install django == x.x.x
x.x.xは指定したいバージョン


次に入れるのは "Gunicorn""Uvicorn" です。
リンク
Gunicorn 公式

本来GunicornはNginxとDjangoをつなぐWSGIサーバーとして使用されます。

しかし今回はWSGIでは無くASGIですので、ASGIサーバーとしてUvicornを使用します。
リンク
Uvicorn 公式

Uvicornは非同期対応のGunicornみたいなものです。

そしてNginxとDjangoを繋ぐ役割を担うUvicornのプロセスマネージャとしてGunicornを利用します。
(venv) $ pip3 install gunicorn uvicorn
設定関係はあとでやりますので、まずは必要なものだけ先に入れます。

次はPostgreSQLをPythonから操作する為のライブラリであるpsycopg2をインストールします。
(venv) $ pip3 install psycopg2-binary


ここまでで最低限必要なものは揃いました。

開発したアプリに必要なライブラリがあれば、各々別途インストール下さい。



2.3 - gunicornの設定


Gunicornをプロセスマネージャとして使いつつ、Uvicornを起動する設定を行います。

まずsystemdのユニットファイルを作成し、Gunicornのサービスを定義します。

自作のサービスは /etc/systemd/system に作成します。

ファイル名は "gunicorn.service" とします。
$ cd /etc/systemd/system
$ sudo vim gunicorn.service


中身は下記のようにして保存します。
/etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn
Requires=プロジェクト名.socket
After=network.target


[Service]
User=ユーザー名
Group=www-data
WorkingDirectory=/home/ユーザー名/プロジェクト名
ExecStart=/home/ユーザー名/venv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/ユーザー名/プロジェクト名/プロジェクト名.sock config.asgi:application -k uvicorn.workers.UvicornWorker


[Install]
WantedBy=multi-user.target
ユーザーのホームディレクトリにDjangoのプロジェクトを置く前提の設定内容です。
※ここまでの解説ではまだプロジェクトは置いていない状態です。

git clone等で開発したアプリのプロジェクトをユーザーのホームディレクトリに配置しておいて下さい。
/home/ユーザー名/
|-- プロジェクトフォルダ
| |-- プロジェクト名.sock
| |-- config
| |-- mainapp
| `-- manage.py
`-- venv
|-- bin
|-- lib
|-- pyvenv.cfg
`-- share
こんな感じの配置です。
"プロジェクト名.sock" は後で生成されますので、今はまだ無くても気にしなくてOKです。


補足
プロジェクトファイル:
Djangoで作成したプロジェクトフォルダのこと。
プロジェクトフォルダの中には "manage.py""アプリケーション" 等が入っています。


続いてプロジェクトフォルダのパーミッションを変更します。
$ sudo chmod 775 プロジェクトフォルダ名
書き込み権限を与えないとGunicorn起動時に「.sockが無い」というエラーが出ます。

Gunicornの自動起動を有効にします。
$ sudo systemctl enable gunicorn.service


あとはGunicornを起動すればOKです。
$ sudo systemctl start gunicorn.service
ちなみですが、最後の ".service" は省略しても問題ありません。



2.4 - 静的ファイルの配信設定


Javascriptファイル(.js)やCSSファイル(.css)など、静的なファイルと呼ばれるもの達を配信するフォルダ設定を行います。

Djangoには静的ファイル(static)を配信フォルダに一括で集めるコマンド「collectstatic」があります。

このコマンドを実行したときにファイルを集める場所を決めます。


補足
開発環境ではプロジェクトフォルダのmanage.pyと同じ階層に "static" フォルダを作ることが多いですが、本番環境ではプロジェクトフォルダ内には設置せず、別の場所に置くことがあるようです。
リンク
teratail - なぜWebデータを/var/wwwに置かないといけないのか?


その後、集めた静的ファイルをNginxから配信できるように設定します。


まず静的ファイルを集める場所ですが、ザクッと調べたところ下記に置いている人が多いようです。
  • /var/www
  • /usr/share/nginx
  • /home/ユーザー名/プロジェクトフォルダ
私は /var/www を採用していますので、その前提で解説を進めます。
別のディレクトリを選んだ方は適宜パスを脳内変換して読んで下さい。

ここからの手順は下記の通りです。
  1. staticフォルダの設置
  2. 設定ファイルの作成
  3. 設定ファイルリンクの設置


staticフォルダ、つまり静的ファイルの置き場所を作ります。
場所は先程選んだ /var/www です。
$ cd /var/www
$ sudo mkdir 好きなフォルダ名
"好きなフォルダ名" はプロジェクト名にしておくと分かりやすいです。


補足
この場所はDjangoの設定ファイル "settings.py""STATIC_ROOT" と整合がとれているようにしましょう。
settings.py
PROJECT_NAME = 'プロジェクト名'
STATIC_ROOT = '/var/www/{}/static'.format(PROJECT_NAME)
この設定が正しくないと「collectstatic」コマンドで /var/www ~ に静的ファイルが集まりません。

続いて設定ファイルを作成します。

設定ファイルは /etc/nginx/sites-available に作成します。
$ cd /etc/nginx/sites-available
$ sudo vim プロジェクト名
デプロイするアプリの設定ファイルと分かるように、ファイル名を "プロジェクト名" としておきましょう。

中身は下記のようにして保存します。
/etc/nginx/sites-available/プロジェクト名
server{
listen 80;
server_name サイトのIPアドレス;


location =/fabicon.ico {access_log off; log_not_found off;}
location /static/{
root /var/www/プロジェクト名;
}


location /{
include proxy_params;
proxy_pass http://unix:/home/ユーザー名/プロジェクトフォルダ名/プロジェクト名.sock;
}
}
"サイトのIPアドレス" はドメインを取得したら "ドメイン名" に書き換えます。
後ほどSSL接続設定やリダイレクト設定の際にこの設定ファイルを編集します。


最後に設定ファイルのリンクを /etc/nginx/sites-enabled に作成します。
$ sudo ln -s /etc/nginx/sites-available/プロジェクト名 /etc/nginx/sites-enabled/
シンボリックリンクを作成しました。

シンボリックリンクが作られているか確認します。
$ cd /etc/nginx/sites-enabled
$ sudo ls -l
lrwxrwxrwx 1 root root 36 11月 20 23:15 プロジェクト名 -> /etc/nginx/sites-available/プロジェクト名
"プロジェクト名" というシンボリックリンクが作成されており、リンク先は先程作った設定ファイルになっています。


静的ファイルの配信設定およびNginxの初期設定は以上です。



2.5 - ドメインの取得&設定


今回は ムームードメイン を選びました。

ドメインは下記記事を参考に取得し、DNSの設定まで済ませておいて下さい。
リンク
ホームページの作り方⑥ドメイン


補足
DNS設定の際、ネームサーバの反映までに数日掛かると書いてありましたが、私の場合は設定して数分で繋がるようになっていました。
ConoHaの運営会社 "GMOインターネット" がムームードメインの運営会社 "GMOペパポ" の親会社だからでしょうか?
とにかく反映が早かったです。


ドメインを取得したら下記の設定ファイルを書き換えます。
  • settings.py
  • Nginx設定ファイル

settings.py
ALLOWED_HOSTS = ["ドメイン名"] # 例えば example.com
環境変数 ".env" を使用している場合は、そちらの設定ファイルを書き換えましょう。

/etc/nginx/sites-available/プロジェクト名
server_name ドメイン名;


ドメイン設定は以上です。


2.6 - 常時SSL化


以前にも常時SSL化について記事を書きました。
リンク
ホームページの作り方⑦常時SSL接続化

但し、今回は環境が異なりますので実施方法も異なります。

前回
  • Cent OS
  • Apatch
今回
  • Ubuntu
  • Nginx

というわけで解説します。


今回もSSL化には "Let's Encrypt" を使わせてもらいます。

まずはインストール。
$ sudo apt install letsencrypt


続いてcffiをインストール。
※"No module named '_cffi_backend'" というエラーが出ないように入れときます。
$ sudo pip install -U cffi


一旦nginxを停止させます。
$ sudo systemctl stop nginx



下記コマンドで証明書を取得します。
$  letsencrypt certonly --standalone -d ドメイン名 # 例えば example.com

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator standalone, Installer None
Enter email address (used for urgent renewal and security notices) (Enter 'c' to cancel): メールアドレスを入力

---
規約に同意しますか?的な文章
---
(A)gree/(C)annel: A # 同意

---
メールアドレスをLet's Encryptの支援者に共有しても良いですか?的な文章
---
(Y)es/(N)o: N # 拒否 (もちろんYでもOKです)
何事もなく成功すると、下記のメッセージが表示されます。



この2つはこの後使います。
/etc/letsencrypt/live/ドメイン名/fullchain.pem
/etc/letsencrypt/live/ドメイン名/privkey.pem


nginxの設定ファイルを書き換えます。
/etc/nginx/sites-available/プロジェクト名
server{
listen 80;
listen [::]:80;
server_name ドメイン名;
return 301 https://$host$request_uri;
}


server{
listen 80;
listen 443 ssl http2;
server_name ドメイン名;
ssl_certificate /etc/letsencrypt/live/ドメイン名/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ドメイン名/privkey.pem;
return 301 https://ドメイン名$request_uri;
}


server{
listen 443 ssl http2 default_server;
server_name ドメイン名;
ssl on;
ssl_certificate /etc/letsencrypt/live/ドメイン名/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ドメイン名/privkey.pem;


location =/fabicon.ico {access_log off; log_not_found off;}
location /static/{
root /var/www/プロジェクト名;
}

location /{
include proxy_params;
proxy_pass http://unix:/home/ユーザー名/プロジェクトフォルダ名/プロジェクト名.sock;
}
}
これでSSL化の設定が完了しました。

nginxとgunicornを再起動し、設定を反映させます。
$ sudo systemctl restart nginx
$ sudo systemctl restart gunicorn



2.7 - 動作確認


長かった準備がやっと終わりました。

デプロイしたサイトにアクセスして、しっかり動いているか確認しましょう。

https://example.com

"http" でもアクセスし、"https" にリダイレクトされるかチェックです。

問題なければ動作確認OKです。



3. 後は運用


準備お疲れ様でした!

ようやくウェブアプリを公開することができましたね!

でもここからがスタートです。

やることは山積みだと思いますので、無理せず頑張ってください。