FlaskとuwsgiでREST APIをUbuntunサーバーにデプロイする設定方法を徹底解説したよ

激安VPS・WebARENA IndigoVPSで試してみる

WebARENA Indigo VPSはNTTグループが提供する激安VPSです。

月額349円(税込み)でメモリ1GBのVPSが借りれます。

⇩Indigo VPSについての解説は過去記事を参考にしてください。

WebARENAの新しいVPSサービスIndigoに登録してみてわかったメリット・デメリットを徹底解説

このIndigo VPSにFlaskアプリをデプロイする方法を解説していきます。

Flaskはuwsgiというアプリケーションサーバーを介してNginxなどのサーバーアプリケーションに接続します。そこの設定がちょっとややこしいので詳しく解説します。

サーバーの設定を行う

サーバーのアップデートを行う

sudo apt-get update

Nginxをインストールする

sudo apt-get install nginx

ファイアーウォールの設定を行う

ubuntuでファイアーウォールを操作するコマンドであるufwを使って、

VPSへのリモート接続に必要なSSH通信と、

NginxだけにHTTP通信を許可する。

逆にいうと他の通信はファイアーウォールでブロックする設定を行います。

まずはファイアーウォールの状態確認を行います。

sudo ufw status

初期状態ではファイアーウォールのサービス自体がオフ(inactive)になっています。

Status: inactive

Command may disrupt existing ssh connections. Proceed with operation

ssh接続はファイアーウォールを通過できるように設定します。

これでファイアーウォールをオン(起動)にしてもリモート接続できます。

sudo ufw allow ssh

ファイアーウォールを起動します。

sudo ufw enable

ちゃんと設定しないでファイアーウォールを起動するとリモート接続できなくなりますよと警告されます。ちゃんと設定したのでy(yes)と入力します。

Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

ファイアーウォールの状態確認を行います。

sudo ufw status

ステータスがactiveになっていることを確認してください。

Status: active

To Action From
-- ------ ----
22/tcp ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)

となります。

次にNginxによるHTTP接続を許可する。

sudo ufw allow 'Nginx HTTP'
sudo ufw status
Status: active

To Action From
-- ------ ----
22/tcp ALLOW Anywhere
Nginx HTTP ALLOW Anywhere
22/tcp (v6) ALLOW Anywhere (v6)
Nginx HTTP (v6) ALLOW Anywhere (v6)

Nginx HTTPがファイアーウォールを通過することが許可されました。

これでNginxは外部からのHTTP通信に対してレスポンスできるようになった。

Nginxの状態を確認します。

systemctl status nginx

起動していないはずなので起動します。

sudo systemctl start nginx

停止するときはstopです。

sudo systemctl stop nginx

再起動したいときはrestartです。

sudo systemctl restart nginx

nginxの設定を行う

sudo vim /etc/nginx/sites-available/items-rest.conf
server {
listen 80;
real_ip_header X-Forwarded-For;
set_real_ip_from 127.0.0.1;
server_name localhost;

location / {
include uwsgi_params;
uwsgi_pass unix:/var/www/html/items-rest/socket.sock;
uwsgi_modifier1 30;
}

error_page 404 /404.html;
location = 404.html {
root /usr/share/nginx/html;
}

error_page 500 502 503 504 50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

availableというのは”利用できる”という意味でenabledというのは"有効化する・作動させる・スイッチを入れる"という意味ですので、sites-availableに様々な設定を用意しておき、必要に応じて、enabledにシンボリックリンクをはって、有効化します。

sudo ln -s /etc/nginx/sites-available/items-rest.conf /etc/nginx/sites-enabled/

/etc/nginx/sites-enabled/items-rest.confというシンボリックリンクを作成します。

rest-apiで作成されたプロジェクトをgitで/var/www/html/items-rest内にクローンしてきます。

sudo mkdir /var/www/html/items-rest
sudo chown ubuntu:ubuntu /var/www/html/items-rest
cd /var/www/html/items-rest
git clone https://github.com/schoolofcode-me/stores-rest-api.git .
mkdir log

python3のインストールとvirtualenvの導入

デフォルトのpythonのバージョンが2.7なので3.6にする

sudo apt-get install python-pip python3-dev libpq-dev

virtualenvをインストールしてPython3.6のvenv環境を作成します。

環境をアクティベートして、pipで必要なライブラリをインストールします。

requirements.txtには必要なライブラリが記載されています。

sudo apt install virtualenv
pip install virtualenv
virtualenv venv --python=python3.6
source venv/bin/activate
pip install -r requirements.txt

 

sudo vim /etc/systemd/system/uwsgi_items_rest.service

このサービスの管理ユーザーはubuntuとしています。

ユーザーが異なる時はubuntuという部分を適宜変更してください。

--uid ubuntu --gid ubuntu

[Unit]
Description=uWSGI items rest

[Service]
Environment=DATABASE_URL=postgres://ubuntu:1234@localhost:5432/ubuntu
ExecStart=/var/www/html/items-rest/venv/bin/uwsgi --master --emperor /var/www/html/items-rest/uwsgi.ini --die-on-term --uid ubuntu --gid ubuntu --logto /var/www/html/items-rest/log/emperor.log
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all

[Install]
WantedBy=multi-user.target

作成できればsystemctlで作成したuwsgi_items_restというサービスを起動します。

/etc/systemd/system以下に.service設定ファイルを作成すればなんでもサービス化できるわけですね。

sudo systemctl start uwsgi_items_rest

初めてサービスを起動すると警告が出ることがあります。

sudo systemctl start uwsgi_items_rest
Warning: The unit file, source configuration file or drop-ins of uwsgi_items_rest.service changed on disk. Run 'systemctl daemon-reload' to reload units.
Job for uwsgi_items_rest.service failed because the control process exited with error code.
See "systemctl status uwsgi_items_rest.service" and "journalctl -xe" for details.

のような警告がでたら、

sudo systemctl daemon-reload

とデーモンをリロード(再読込み)してから再度、

sudo systemctl start uwsgi_items_rest

としてください。

ユーザーの設定

ユーザー権限の設定方法です。

必ずしも必要とは限りませんが、権限の問題でつまづくことがあれば、見直してみてください。

visudoはsudo権限を設定する方法です。

visudo

ubuntu ALL=(ALL:ALL) ALL

これでubuntuには全てのsudo権限が与えられます。

次にsshの設定です。

vi /etc/ssh/sshd_config

PermitRootLogin no
AllowUsers ubuntu

service sshd reload

PostgreSQLのインストールとセットアップ

PostgreSQLをインストールしてセットアップを進めていきます。

sudo apt-get install postgresql postgresql-contrib

10+190ubuntu0.1

PostgreSQLをインストールするとpostgresというLinuxユーザーが作成されるので、以下のコマンドでpostgresというユーザーになります。

sudo -i -u postgres

初期状態ではpostgresというユーザーのみにPostgreSQLの操作・変更権限が与えられているので。

まずこのpostgresにログインしてPostgreSQLの新規ユーザーとデータベースを作成します。

createuser で新規にpostgreSQLのユーザー(ここではubuntu)を作成します。

ここでは新規ユーザー名:ubuntu, データベース名:ubuntuとしました。

パスワードを設定します。

createuser ubuntu -P

データベースを作成します。

createdb ubuntu

データベースへの接続の際の認証のルールを設定します。

vim /etc/postgresql/10/main/pg_hba.conf

pg_hba.confファイルはデータベースへの接続の際の認証のルールの設定ファイルです。

# "local" is for Unix domain socket connections only
local   all             all                                     peer

という部分のpeerをmd5に変更します。

local内でデータベースへの接続ではデフォルトではPeer認証となっています。

Peer認証とは、カーネルからクライアント上のシステムユーザ名を取得し、PostgreSQLデータベースユーザと同一である場合のみ接続が許可される仕組みです。 つまり、Postgresql内のユーザーとUNIXユーザで、ユーザー名が一致してさえいれば認証情報なしでログイン出来てしまう仕組みです。

Peer認証ではあまりにもセキュリティ的にアレなので、「パスワード認証」であるmd5認証これに設定します。

# "local" is for Unix domain socket connections only
local   all             all                                     md5

ちなみに直接コマンドでデータベースをいじりたい場合はpsqlを使います。

psql

\q ⇨ psqlから出る時

Flaskアプリをuwsgiに接続する

uwsgi.iniの設定

/var/www/html/items-rest

内にuwsgi.iniという起動ファイルを設置します。

[uwsgi]
base = /var/www/html/items-rest
app = run
module = %(app)

home = %(base)/venv
pythonpath = %(base)

socket = %(base)/socket.sock

chmod-socket = 777

processes = 8

threads = 8

harakiri = 15

callable = app

logto = /var/www/html/items-rest/log/%n.log

/var/www/html/items-rest/socket.sockというファイルを作成しこれを利用してNginxと通信します。

このsocket.sockというファイルは特別なファイルで、インターフェースとして機能します。

プロセス間の高速な通信としてファイルというインタフェースを利用するわけです。

決してこのファイルに何かが書き込まれて、それをuwsgiが読み出して、みたいなことはしていません。

コメント