bottle+pythonの外部公開

簡易的な動作確認

サーバでpython3をインストールする。
yum install -y https://centos7.iuscommunity.org/ius-release.rpm
yum install -y python36u python36u-devel python36u-libs

pythonでwebアプリを開発するbottleをインストールする。
pip3 install bottle

その後、以下のディレクトリに移動する。

cd /var/www/

この中に、コンテンツ用のディレクトリxxxを作る。

mkdir xxx

コンテンツを外部から置けるようにするため、このディレクトリの権限を変更する。
chown apache:zzz xxx
chmod 775 xxx
zzzは一般ユーザ名、CyberDuckでファイルを転送するユーザとする必要がある。
次に、CyberDuckで、test.py、bottle.pyとサーバ構成用pyファイルをアップロードする。test.pyは以下の通りである。

from bottle import route, run
 
@route("/sample")
def index():
    return "Hello!"
 
run(host='0.0.0.0', port=50000)

hostはこのアドレスで固定する。portは何番でも良い。

次に、pyファイルで指定しているポートを解放する。

firewall-cmd  --permanent --add-port=50000/tcp
firewall-cmd --reload

そのあと、ターミナルからサーバ構成用pyファイルを起動する。
python3 test.py

ブラウザからアクセスできれば成功です。
http://xxx.xxx.xxx.xxx:50000/sample
http://[ドメイン名]:50000/sample

サーバを切断する場合には、control+cを押す。


バックグラウンド実行

前述の方法だと、公開している間、ターミナルで他の操作が出来なくなるし、ログアウトもできなくなる。
これは不便なので、バックグラウンドで動作させる。このためには、nohupと&でコマンドを囲えば良い。

nohup python3 yyy.py &

なお、この操作は、pyファイルをおいてあるディレクトリで実施しなければならない
(pyファイルのテンプレートが相対パスしか使用できないため)。
実行を終える場合は、ターミナルで「ps u」と打ち込み、起動しているPIDのナンバーを探し、それを「kill zzz」でkillする(zzzはPIDのナンバー)。


本番環境でのデプロイ

前述した方法だと、毎回ターミナルから手打ちでサーバを起動しなければなりません。これはかなり煩わしいので、apacheとwsgiを利用して自動的にサーバを立てる方法について述べます。

wsgiと呼ばれる、webサーバとpyファイルの接続を担うツールをインストールします。


yum -y install httpd-devel
python3 -m pip install mod_wsgi

次に、もう一度以下のコマンドを打つと、mod_wsgiのありかが出てきます。


python3 -m pip install mod_wsgi

「mod_wsgi in /usr/lib64/python3.6/site-packages」ときた場合、このディレクトリに移動します。site-packgesの下層にmod_wsgi/serverというディレクトリがあり、その中に入ると、mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.soがあります。このファイルのフルパスを覚えておきます。参考までに、Cent OS7の場合は、「/usr/lib64/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so」となります。これをメモっておきます。

次に、https.confによりapacheの設定ファイルを開きます。

vim /etc/httpd/conf/httpd.conf

httpd.confが開くので、以下があるか探します。

IncludeOptional conf.d/*.conf

もしあれば、conf.dディレクトリにある*.confファイルを自動でロードしてくれることになります。ない場合は追加してください。その後、設定ファイルbottle.confを作ります。

vim /etc/httpd/conf.d/bottle.conf

このコマンドで、bottle.confが作成されます。この中に、以下のように記述します。

Listen 80
<VirtualHost *:80>
DocumentRoot /var/www/html/
ServerName AAA.com
</VirtualHost>

Listen 50000
LoadModule wsgi_module /usr/lib64/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
<VirtualHost *:50000>
  DocumentRoot /var/www/Contents
  ServerName AAA.com
  WSGIScriptAlias / /var/www/Contents/adapter.wsgi
  <Directory "/var/www/Contents">
   AddHandler wsgi-script .wsgi
   AddHandler wsgi-script .py
   Options ExecCGI
   DirectoryIndex adapter.wsgi
  </Directory>
</VirtualHost>

今回、80番ポートと50000番ポートの2つにコンテンツが置かれているとします。それぞれにそれぞれのコンテンツがあるとします。また、自分のドメインを「AAA.com」とします。もしドメインがない場合は、サーバのipアドレスでも良いです。80番ポートはbottle以外(例えば、WordPressなど)が動いているとします。そして、50000番ポートをbottleとPythonで作成したコンテンツとします。

DocumentRoot:
「/var/www/Contents」とします。すなわち、「http://AAA.com:50000」にアクセスしたとき、このディレクトリにアクセスすることを意味します。

AddHandler & Options:
ここでは、.wsgiと.pyの実行を許可しています。pythonでサーバを構築する場合は、この拡張子を実行可能とする必要があるためです。

DirectoryIndex:
「http://AAA.com:50000」にアクセスしたとき、実行されるファイルです。今回は、「adapter.wsgi」とします。

WSGIScriptAlias:
「adapter.wsgi」が置かれているディレクトリをフルパスで指定します。

LoadModule:
「mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so」が置かれている場所を、フルパスで指定します。

次に、bottle.conf側で80番ポートを指定したので、httpd.conf側を開き「Listen 80」を「#Listen 80」に変更し、無効化します。
これをしない場合、80番ポートはすでに使われているという理由で、httpdのリスタート時にエラーが出ます。

次に、50000番ポートを解放します。


firewall-cmd --permanent --add-port=50000/tcp
firewall-cmd --reload

続いて、DocumentRootで指定した「/var/www/Contents」に、adapter.wsgiと、サーバのpyファイル(XXX.py)を置きます。adapter.wsgiは以下のようになります。XXXは拡張子を書いていないpyファイルですので、注意してください。


# coding: utf-8
import sys, os
import bottle

dirpath = os.path.dirname(os.path.abspath(__file__))
sys.path.append(dirpath)
os.chdir(dirpath)

import XXX
application = bottle.default_app()

また、XXX.pyはサンプルとして以下の通りとします。


from bottle import route, run, template
from bottle import TEMPLATE_PATH

@route('/')
def index():
    return "Deploy! Bottle!"

# runはコメントアウトすること!
# run(host='AAA.com', port=50000)

注意点、run関数は必ずコメントアウトしてください。
次に、bottleが読めないと言われないように、bottleもインポートしておきます。


python3 -m pip install bottle

そして、コンテンツが置かれているディレクトリすべてのフルパスで、権限を755に変えて置く。

chmod 755 adapter.wsgi

これで外部公開する権限の設定ができました。最後に、httpdをリスタートします。


systemctl restart httpd

もし、リスタートがうまくいかない場合は、httpdが不正状態にあるので、プロセスをkillします。killすべきプロセスIDは以下のコマンドで調べることができます。

ps aux | grep httpd

killは以下のコマンドです。yyyはプロセスの数字です。一番上のプロセスをkillすればokです。


kill yyy

その後、httpdをstopしてstartします。


systemctl stop httpd
systemctl start httpd

どうしてもうまくいかない場合は、以下のコマンドでエラーを確認できます。


systemctl status httpd.service
vim /etc/httpd/logs/error_log

最後に、ブラウザで「AAA.com:50000」と入力します。これでコンテンツが表示されれば成功です。バーチャルホストとしているので、「AAA.com:80」でもコンテンツが表示されるようにしてあります。


インテリジェントなシステムにしたい場合

もし、コンテンツに機械学習などを入れたい場合には、以下を入力します。

インストール関係:
$ sudo yum install -y python36u-pip
$ sudo python3 -m ensurepip

pipコマンドは、以下で使用可能になる。
$ python3 -m pip install

$ python3 -m pip install jinja2
$ python3 -m pip install numpy
$ python3 -m pip install sklearn
$ python3 -m pip install matplotlib