Raspberry pi + Nginx + uWSGIでWebサーバーを立ち上げDjangoアプリをデプロイしてみる その1

##はじめに
はじめまして、ochomaki（おちょまき）と申します。横浜でWebエンジニアをやっています
今回がQiita初投稿になりますので不慣れな点もありますが適宜改良を加えていくのでアドバイスいただければ幸いです。

本記事ではRaspberry pi(3B)にNginxとuWSGIをインストール、Webサーバーを立ち上げてDjangoアプリを表示させるところまで行います。最後までお付き合いいただければ幸いです
この記事はuWSGIのチュートリアル
[Setting up Django and your web server with uWSGI and nginx — uWSGI 2.0 documentation](http://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html) を参考にしています。

##Raspberry piとは
Raspberry piとは、ARMプロセッサを搭載したシングルボードコンピューター。イギリスのラズベリーパイ財団によって開発されている。日本では略称としてラズパイとも呼ばれる(Wikipediaより抜粋）

現在の最新版は[Raspberry Pi 4 Model B](https://amzn.to/2yfUNiB)になります。ちなみに私は[Raspberry Pi 3 Model B](https://amzn.to/33Re2uc)で本記事の内容を実行しておりますが、どのバージョンでも基本問題はないはずです。

端的に言えば小さなPCです。サイズはだいたいタバコの箱程度と、とてもコンパクトな上に安価で消費電力も少ないためIoT機器に用いられる事も多いみたいです。
今回Webサーバーとして使ってみようと思ったのも、消費電力が少ないため常時起動していても財布が痛まない事が理由だったりします。
また、LinuxベースのOS（Raspbian)を搭載できるので性能は控えめですが普通のPCとして利用できます。実際、この記事はRaspberry pi上でブラウザを起動して書いてます。

そのうちRaspberry piのセットアップについての記事も書いてみようと思います。


##Pythonの仮想環境構築
Raspberry piに標準搭載されているPythonのバージョンは3.5.3と少し古いため3.7.2をインストールしし、デフォルトのバージョンに設定します。また、今回のプロジェクト(？)用に仮想環境も構築します。
仮想環境の構築はこちら [[2019年]raspberry pi初期設定(pipenv導入まで)](https://qiita.com/meznat/items/e73ba7d62ce60ae4d479) を参考にさせてもらっています。それでは始めましょう

```python:terminal
# 標準搭載のPythonのバージョンを確認
$ python3 -V
Python 3.5.3
```
まずはgitを使ってpyenvをインストールします。pyenvとはプロジェクトごとにpythonの仮想環境を構築することが出来るアプリケーションです。今回はPythonのビルドでのみ使用します。以下のコマンドを順次実行しましょう。

```python:terminal
$ sudo apt install git    # gitのインストール
# pyenvのgitリポジトリのクローン
$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv
# ~/.bash_profile に以下の3行を追記します
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
# ~/.profile にも同じ内容を追記します(6/2追記 参照)
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.profile
$ echo 'eval "$(pyenv init -)"' >> ~/.profile
$ exec $SHELL
$ sudo reboot    # Raspberry piの再起動を行います
```

(6/2追記)
この記事の内容をすべて実行した後、ラズパイを再起動したら何故かPythonのバージョンが3.5.3に戻るという現象が起きていました。調べたところ偉大なる先人様
[【Raspberry pi 3B+】bash_profileの設定が読まれないので調べたbash関連のメモ](https://tori-pun.com/raspberrypi_bash_shell_setting_1/) を参考にさせて頂いたところ、無事解決することができたので報告します。

要約すると
○ 本来はラズパイ起動時に~/.bash_profileが読み込まれ、PATHの設定が反映される
○ 何故か~/.bash_profileが読み込まれない
○ ~/.bash_profileが存在しない場合に読み込まれる~/.profileに~/.bash_profileと同じ内容を追記
○ ~/.profileが無事読み込まれ無事解決！
という流れです。今後も~/.bash_profileに追記する必要がある場合は~/.profileにも書いておいたほうがいいかもしれません。

```python:terminal
# ビルドに必要なライブラリをインストールします
$ sudo apt-get install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev
$ sudo apt-get install libffi-dev
```
先程インストールしたpyenvを使ってPython3.7.2をインストールします。

```python:terminal
$ source ~/.bash_profile
$ pyenv install 3.7.2    # Python3.7.2をインストール
$ pyenv global 3.7.2    # Python3.7.2をデフォルトの設定にする
```
これでPython3.7.2へのアップデートは完了です。バージョンを確認してみましょう。```python 3.7.2```　と表示されていれば成功です

```python:terminal
$ python3 -V
python 3.7.2
```
次はpipenvをインストールします。pipenvとはPython公式のパッケージ管理ツールです。以下公式から抜粋した説明です

`Pipenvは、手動でパッケージのインストールおよびアンインストールを行うのと同じように Pipfile に対してパッケージの追加および削除を行うのに加え、自動でプロジェクト用の仮想環境を作成し管理します。 またPipenvは、いかなるときも重要な Pipfile.lock を生成し、これを利用しビルドが常に同じ結果になるようにします。`

それではpipenvをインストールしましょう

```python:terminal
$ pip install --upgrade pip    # 先にpipを最新版にアップグレードします
$ pip install pipenv    # pipenvをインストールします
```
pipenvをインストールできましたら次は仮想環境の構築に移ります。今回は/home/pi 上にTestディレクトリを作成し、そこに仮想環境を構築します。仮想環境を構築後、DjangoとuWSGIをインストールしていきます

```python:terminal
$ mkdir ./Test    # Testディレクトリを作成
$ cd ./Test    # Testディレクトリに移動
$ pipenv install --python 3.7.2 #3.7.2で仮想環境構築

$ pipenv install Django    # 仮想環境にDjangoをインストール
$ pipenv install uwsgi    # 仮想環境にDjangoをインストール
$ pipenv shell #仮想環境を実行
```

仮想環境実行後はターミナルの表示の先頭が(Test)になっているはずです。これは仮想環境(Test)を実行中である、という事を示しています。仮想環境から抜ける際は `exit` を入力すれば抜けられます。


##Djangoプロジェクトの作成
先程仮想環境にインストールしたDjangoを使いDjangoプロジェクトを作成します。今回はチュートリアルに沿いプロジェクト名をmysiteとします。
今回のプロジェクト用に作成したTestディレクトリにプロジェクトを作成します。プロジェクトが作成されると、Testフォルダ上にプロジェクトのフォルダ(mysite)が生成されます。

```python:terminal
# プロジェクト(mysite)の作成
$ django-admin.py startproject mysite
```

## uWSGIの動作確認
先程仮想環境にインストールしたuWSGIについて軽く触れようと思います。
uWSGIとはアプリケーションサーバの一種であり、以下の構成のの通りWebサーバとWebアプリケーションを繋ぐ位置にあります。Webサーバからのリクエストを受け取り、受け取ったリクエストに応じてアプリケーション（Pythonプログラム）を実行する役割を担います。

```python:全体の構成
ブラウザ <-> Webサーバ(Nginx) <-> Unixソケット/http(通信プロトコル) <-> アプリケーションサーバ(uWSGI) <-> Webアプリケーション(Django)
```
それではuWSGiを使ってみましょう。まずは /home/pi/Test/mysite にtest.pyを作成し、以下の内容を入力して保存します。

```python:test.py
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"]
```
次はuWSGIを起動してみます。以下のコマンドを打ち込んでください。コマンドの意味は
○ http :8000 -> HTTPプロトコルを使って通信。ポートは8000を使用
○ wsgi-file test.py -> test.pyを実行


```python:terminal
$ cd mysite # mysiteディレクトリに移動
$ uwsgi --http :8000 --wsgi-file test.py
```
[http://127.0.0.1:8000](http://127.0.0.1:8000)
にアクセスして「Hello World」が表示されていれば成功です。これはブラウザがuWSGIを通してPythonのプログラム(test.py)にアクセスできた事を意味します。
確認が終わりましたら `Ctrl + C ` でuWSGIを停止してください。

## Djangoプロジェクトでテスト

まずはDjangoの実行サーバーでDjangoサイトが実行できるか動作確認をしてみましょう。下記コマンドをmysiteディレクトリで実行してください。

```python:terminal
$ python3 manage.py runserver
```
上記コマンドを実行後 [http://127.0.0.1:8000](http://127.0.0.1:8000) にアクセスし以下のサイトが表示されれば成功です。動作確認が済みましたら `Ctrl + C ` でサーバーを停止してください。

![djangoSite_SS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424307/3f994bcc-e337-d782-39aa-0bccb594dd19.png)


次は、先程test.pyで「Hello World」を実行した代わりに、uWSGIでDjangoサイトを実行してみます。mysiteディレクトリで下記コマンドを実行し、[http://127.0.0.1:8000](http://127.0.0.1:8000) にアクセスしてみてください。

```python:terminal
$ uwsgi --http :8000 --module mysite.wsgi
```
先程表示したDjangoサイトが表示されていれば成功です。uWSGI経由でDjangoプロジェクトを呼び出すことが出来ました。

```python:現在の構成
ブラウザ <-> アプリケーションサーバ(uWSGI) <-> Webアプリケーション(Django)
```
現段階での構成は上記の通りになりますが、本来uWSGIはブラウザとは直接やりとりはせず、Webサーバーを中継します。次の回ではそのWebサーバーであるNginxをインストールし、構成に組み込んでいきます。

## 次回はこちら
[Raspberry pi + Nginx + uWSGIでWebサーバーを立ち上げDjangoアプリをデプロイしてみる その2](https://qiita.com/ochomaki/items/51ea5f72fe477e3890ca)

####最終回はこちら
[Raspberry pi + Nginx + uWSGIでWebサーバーを立ち上げDjangoアプリをデプロイしてみる その3(最終回)](https://qiita.com/ochomaki/items/685959ced864d2b6feac)