JUNのブログ

JUNのブログ

活動記録や技術メモ

GCE + Nginx + uWSGI + Django + Supervisor を使ってDjangoアプリをデプロイ

はじめに

GCE とは Google Cloud Platform Compute Engine の略である。この記事ではWebアプリを公開するところまでを記述してある。

注意点として、この記事ではGCPのアカウント登録等については触れず、既にGCPのアカウントとクレジットカード登録による無料クレジットの獲得まで完了していることを前提に話をすすめる。

サーバーの環境は以下の構成

Ubuntu + Nginx + uWSGI + Django これにさらにインスタンス起動時に自動でWebアプリを起動させるためにSupervisorを導入する。 Djangoアプリは既に作成済みとし、それをWeb上で公開できることをゴールとする。
注意点としては、今回の記事では仮想環境等はめんどうなので入れません。

大まかな手順

  1. GCP Compute EngineでUbuntuベースでインスタンスを作成
  2. いろいろインストールする。
  3. Djangoアプリをサーバーにコピーする
  4. Nginx+uWSGI+Supervisorを使ってデプロイと自動起動

インスタンスの作成

GCP Compute Engine のインスタンスを作成します。 各種設定項目については重要な部分だけ説明します。

  • ゾーン: ここは値段の安いUS圏であるus-central1-aを選択。
  • マシンタイプ: つまりスペック。あとから変更できるので、最初は色々インストールするので最初だけスペックを上げておいてもいいかも。
  • ブートディスク: ここではOSの種類と、HDD/SSDの容量を設定できる。OSはUbuntuで、サイズは10GBで大丈夫。これもあとから変更できる。
  • ファイアウォール: HTTPトラフィックのところにチェックすると、httpのデフォルトポート番号である80番でアクセスできるようになるのでチェックを入れる。

Djangomanage.py runserver用に8000番ポートを開ける

デフォルトの状態では8000番が開いていないので、設定して開ける。 まず左のメニューバーからVPCネットワークを選び、その中のファイアウォールルールを選択する。
そこから、ファイアウォールルールの作成を選び、ファイアウォールルールを作成する。

重要な部分のみ説明。

  • ネットワーク: defaultのままでおk
  • 優先度: 値が小さいほどその設定の適応される順番が上がる。けど、デフォルトの1000のままでいい
  • トラフィックの方向, 一致したときのアクション: デフォルトのままでおk
  • ターゲット: 指定されたターゲットタグを選択
  • ターゲットタグ: ここに入力したタグをインスタンスに登録することでそのインスタンスに作成したファイアウォールルールが適応される。今回はわかりやすいようにdjango-serverというタグで登録する。
  • ソースフィルタ: デフォルトのままでおk
  • ソースIPの範囲: 0.0.0.0/0で全IP指定
  • プロトコルとポート: 指定したプロトコルとポートにチェックを入れ、その下の欄にはtcp:8000と入力

そしたら、作成したインスタンスの編集ページに行き、ネットワークタグに先程作成したファイアウォールルールを適用させりためにdjango-serverというタグを追加する。

これで8000番が使えるようになった。

外部IPを固定する

初期設定だと、インスタンスを再起動するたびに外部IPが変わるので変わらない用に外部IPを固定する。

まず、先程と同じくVPCネットワークにアクセスし、その中の外部IPアドレスにアクセスし、静的IPアドレスを予約を選択し設定する。

重要な部分のみ説明。
- IP バージョン: デフォルトのIPv4に設定 - タイプ: リージョン - リージョン: ここでは先程インスタンスを作成した際に選択したものに近いものを選択する。今回の場合us-central1を選択。 - 接続先: 先程のリージョンの欄で選択したものが正しければ作成したインスタンスが表示されるはずなのでそれを選択。表示されなければリージョンを変えてみてください。
これで再起動しても外部IPが変わらなくなりました。

いろいろインストール

ここまでの作業が完了したら、インスタンスSSH接続しsudo apt-get updatesudo apt-get upgradeを実行し、更新を行う。
そしたら各種ライブラリとかなんかいろいろ入れていく

$ sudo apt-get install python3-pip nginx
$ pip3 install django==2.0.2 uwsgi
$ sudo apt-get install uwsgi uwsgi-plugin-python3
$ sudo apt-get install supervisor

Djangoアプリをサーバーにコピー

SSH上のvimDjangoアプリを作成するのはめんどう大変なので、今回はgithubからコピーします。

$ git clone https://github.com/JUNNETWORKS/polls_project.git
$ ls
polls_project

GitHub - JUNNETWORKS/polls_project: Django2 polls_tutorial
試しにrunserverで動くか試してみましょう

$ cd polls_project
$ python3 manage.py runserver 0:8000

http://外部IP:8000にアクセスし、Not Foundという画面が出ればちゃんと動いてます。

Nginx + uWSGI + Supervisor

uWSGI

とりあえずuWSGIで起動してみましょう

$ uwsgi --master --http-socket=:8000 --plugin=python3 --chdir=/home/ユーザー名/polls_project/ --module=polls_project.wsgi
※ ユーザー名の部分は各自で合わせてください
そしたら、先程と同じページhttp://外部IP:8000にアクセスしNot Foundがでれば無事起動できていることになります。

Nginxのuwsgi用のモジュール設定

uwsgi_paramsをプロジェクト直下に作成

uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;

テンプレートみたいなものなのでとりあえずコピペすれば大丈夫です。

Nginxの設定ファイル

プロジェクト直下にpolls_nginx.confを作成

upstream django {
        # server unix:///www/run/uwsgi/master.sock;
        server 127.0.0.1:8001;
}

server {
        listen      80;
        server_name インスタンスに設定されてる外部IP;
        charset    utf-8;

        client_max_body_size 100M;

        location /static {
                alias /home/ユーザー名/polls_project/polls_project/static;
        }

        location / {
                uwsgi_pass django;
                include    /home/ユーザー名/polls_project/uwsgi_params;
        }

}

そしたらこのコマンドを実行してシンボリックリンクを貼る
$ sudo ln -s ~/polls_project/polls_nginx.conf /etc/nginx/sites-enabled/

静的ファイル

上記のpolls_nginx.confを見わかるとおり、staticファイルは一つの場所にまとめなくてはいけません。 ということで

$ mkdir static
$ python3 manage.py collectstatic

どうしてこのようにしているかはsettings.pyを見るとわかると思います。

Nginx + uWSGI

NginxとuWSGIを使ってちゃんと起動できるか確認しましょう。

$ sudo service nginx restart
$ uwsgi --master --socket=:8001 --plugin=python3 --chdir=/home/ユーザー名/polls_project/ --module=polls_project.wsgi

今度はポート番号を指定せず、http://外部IPにアクセスしてみてください。Not Foundが表示されればNginxを使ってWebページを公開できています。

先程静的ファイルをまとめたので、ちゃんと静的ファイルが適用されてるか確認してみましょう。
http://外部IP/adminにアクセスし、ログイン画面に色がついていたらちゃんと静的ファイルが適用されています。

Supervisorを使ったデーモン化

これでNginx+uWSGIのデプロイは完了したのですが、これではSSH接続を切ったらuWSGIも終了してしまいアクセスできなくなります。
それでは困るので、Supervisorを使ってインスタンスの起動時に自動でuWSGIを起動するようにします。

Supervisorの設定ファイルにpolls_projectを自動起動するための情報を書きます。 /etc/supervisor/conf.d/ にconfファイルを作成します。

$ sudo vim /etc/supervisor/conf.d/polls.conf 中身は以下のようにします。

[program:polls]  ; プロセスの名前
directory=/home/ユーザー名/polls_project  ; 作業ディレクトリ
command=uwsgi --master --socket=:8001 --plugin=python3 --chdir=/home/ユーザー名/polls_project/ --module=polls_project.wsgi  ; 起動コマンド
numprocs=1  ; 起動インスタンス数?
autostart=true  ; autostartする
autorestart=true  ; 自動で再起動させる
user=ユーザー名  ; 起動ユーザ
redirect_stderr=true  ; 標準エラーを出力する
stdout_logfile=/var/log/supervisor/polls.log  ; ログファイルの出力先

設定ファイルを書き終わったらSupervisorを再起動します。

$ sudo service supervisor restart

pollsプロセスが動いてるか確認しましょう。

$ sudo supervisorctl status
polls                            RUNNING   pid 10736, uptime 0:02:16

動いていることが確認できたら再度http://外部IPにアクセスしてみてください。Not Foundが表示されれば自動起動成功です。 この状態でSSH接続を切ってサイトを再読み込みしてみてください。もし再読み込みしても同じNot Foundの表示が出ればデーモン化成功です。

最後にインスタンスを再起動し、もう一度サイトにアクセスしてみましょう。もし先程と同じページが表示されれば成功です。

最後に

これにてGCP Compute Engineを使った Ubuntu + Nginx + uWSGI + Django 構成でWebアプリを公開できました。

このやり方で他のDjangoアプリケーションもデプロイできると思うのでぜひお試しください。

本当は仮想環境を作成して、パッケージ管理をしたり、もっとセキュリティ面うんぬん...などあると思いますが、そこら辺は各自でお願いします。

要望や、質問、間違えの指摘などはコメントにお願いします。

参考サイト

EC2上で Django + Nginx + uWSGI を試す
SupervisorでPythonのWebアプリをデーモン化する