CentOS7+nginx+apache2.4+Python3の環境を作る-apacheとの連携からbottleを使う
前回はpipの設定とmod_wsgiのインストールをしました。今回はapacheとmod_wsgiの連携となります。
注意点
この記事の時点ではまだnginxはいないため、apacheは80番ポートで動いてます。今回の記事はmod_wsgiとapacheを連携してbottleまで動かします
環境
- ベンダー:さくらのクラウド
- OS:CentOS7
- フロント:nginx(80番ポート)
- バックエンド:Apache2.4(8080番ポート)
- Python:3系(pyenvを使用)
- フレームワーク:bottle(8081番ポート)
基本的にsudo環境にする予定です。
手順
基本的には以下の手順になります
- Apacheのインストール
- Python(pyenv)のインストール
- pipの設定
- Apache+Pythonの連携←ここ
- nginxを使ってリバースプロキシ
今回の記事について
今回は手順の4を行います。bottleも使います。nginxとのリバースプロキシが不要の場合は今回の記事で完結となります。
現在の状態
現在はnginxはいないため、このようにそれぞれインストールはされているけど連携はされていないという状態です。今回はこれらを連携させてブラウザで表示できるようにします。
bottleも表示できるようにします
Pythonのフレームワークbottleも使います。なのでnginxとのリバースプロキシが不要な方は今回で終わりです
apacheとmod_wsgiの連携
現在Pythonは使えますが、ブラウザで実際に見るとなるとできません。コマンドでしか実行できません。apacheにはPythonを表示する方法がありません
※例外としてCGIモードにすれば実行できます。
CGIモードだとbottleが使えないかもしれないので、apacheでもPythonを実行できるようにするのがmod_wsgiというモジュールになります。
このモジュールがいることでブラウザでもPythonが使えるようになります
連携させることでこのようになります。mod_wsgiとPythonのとこ連携となっているのは、apacheと連携しても使えないためになります。実際にやっていきたいと思います。
apacheとmod_wsgiを連携させる
まずかmod_wsgiのインストール場所を確認します
[macan@localhost ~]$ pip show mod_wsgi Name: mod-wsgi Version: 4.6.5 Summary: Installer for Apache/mod_wsgi. Home-page: http://www.modwsgi.org/ Author: Graham Dumpleton Author-email: Graham.Dumpleton@gmail.com License: Apache License, Version 2.0 Location: /usr/local/pyenv/versions/3.6.7/lib/python3.6/site-packages Requires: Required-by:
Locationの位置になります。
mod_wsgiをコピーして移動させる
僕のsudo権限ではlsを許可していないため、rootになります。sudoでもlsを許可している方はsudo権限でも問題ありません。
[root@localhost ~]# ls -all /usr/local/pyenv/versions/3.6.7/lib/python3.6/site-packages/mod_wsgi/server/ -rwxr-xr-x 1 root root 945600 11月 12 01:00 mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
モジュールがいました。拡張子.soとなっています。soファイルって何?って方は.soファイルって何?どんなファイルなんですか!を見てください
/etc/httpd/modules/にコピー
[root@localhost ~]# cp /usr/local/pyenv/versions/3.6.7/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so /etc/httpd/modules/
モジュールをコピーしました。実際にあるか確認します
[root@localhost ~]# ls /etc/httpd/modules/ mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
ありました。
Apacheの設定を変更
今やったのはモジュールのコピーです。実際にApacheで動くか確認するため、confファイルなどをいじります。尚、今回のドキュメントルートはApacheのデフォルトの/var/www/html/となります。
httpd.confを修正
httpd.confの最後尾に追記します
LoadModule wsgi_module modules/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so WSGIScriptAlias / /var/www/html/adapter.wsgi
追記をしたら保存をし、シンタックスエラーがないか確認します
[root@localhost ~]# httpd -t AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using localhost.localdomain. Set the 'ServerName' directive globally to suppress this message Syntax OK
Syntax OKがあるので再起動します。AH00558というのは無視して問題ありません。ServerNameがないよって奴なのでドメインなど設定すると消えます。
Apacheの再起動
[root@localhost ~]# service httpd restart Redirecting to /bin/systemctl restart httpd.service
再起動をします
追記したのは二つあります
- LoadModule wsgi_module:ApacheとWSGIを連携させるためにモジュールを読み込みました。
- WSGIScriptAlias:http://IPアドレス/にアクセスしたらadapter.wsgiを実行という意味です
adapter.wsgiの作成
adapter.wsgiを作成していきます。wsgiを動かすのに必要なファイルだと思ってください。
[root@localhost ~]# vi /var/www/html/adapter.wsgi def application(environ,start_response): status = '200 OK' output = b'Hello World!' response_header = [('Content-type','text/plain'), ('Content-Length',str(len(output)))] start_response(status,response_header) return [output]
保存をしたら、http://ipアドレス/にアクセスしてみてください
このようにでたら連携は成功です。
このままPython(bottle)を使ってみたいと思います
Python(bottle)との連携
Apacheとmod_wsgiの連携はできました。このままではPythonを使った事にはなりませんので今度はbottleとの連携をします
bottleのインストール
まずはbottleをインストールします。bottle自体1つのPythonファイルのためインストールは二つあります
- pipを使ってインストール
- wget、SFTPでアップロード
一つ前の記事では、基本的にPython関係は全てpipでインストールすると伝えました。bottleのような単一ファイルならwgetとかでも問題ないです。記事の最後にこのあたりは書いておきます。今回はwgetで持ってきます
[root@localhost ~]# cd /var/www/html/ [root@localhost html]# pwd /var/www/html [root@localhost html]# wget https://raw.githubusercontent.com/bottlepy/bottle/master/bottle.py --2018-11-12 18:58:42-- https://raw.githubusercontent.com/bottlepy/bottle/master/bottle.py raw.githubusercontent.com (raw.githubusercontent.com) をDNSに問いあわせています... 151.101.228.133 raw.githubusercontent.com (raw.githubusercontent.com)|151.101.228.133|:443 に接続しています... 接続しました。 HTTP による接続要求を送信しました、応答を待っています... 200 OK 長さ: 170188 (166K) [text/plain] `bottle.py' に保存中 100%[==================================================================================================================================================================================================================================================================================>] 170,188 --.-K/s 時間 0.05s 2018-11-12 18:58:43 (3.19 MB/s) - `bottle.py' へ保存完了 [170188/170188]
-bash: wget: コマンドが見つかりませんと言われたら、
[root@localhost html]# yum install wget 読み込んだプラグイン:fastestmirror Loading mirror speeds from cached hostfile epel/x86_64/metalink | 7.7 kB 00:00:00 * elrepo: ftp.ne.jp * epel: mirrors.aliyun.com base | 3.6 kB 00:00:00 elrepo | 2.9 kB 00:00:00 epel | 3.2 kB 00:00:00 extras | 3.4 kB 00:00:00 updates | 3.4 kB 00:00:00 (1/2): epel/x86_64/updateinfo | 931 kB 00:00:00 (2/2): epel/x86_64/primary | 3.6 MB 00:00:00 epel 12703/12703 依存性の解決をしています --> トランザクションの確認を実行しています。 ---> パッケージ wget.x86_64 0:1.14-15.el7_4.1 を インストール --> 依存性解決を終了しました。 依存性を解決しました ============================================================================================================================================================================================================================================================================================================================ Package アーキテクチャー バージョン リポジトリー 容量 ============================================================================================================================================================================================================================================================================================================================ インストール中: wget x86_64 1.14-15.el7_4.1 base 547 k トランザクションの要約 ============================================================================================================================================================================================================================================================================================================================ インストール 1 パッケージ 総ダウンロード容量: 547 k インストール容量: 2.0 M Is this ok [y/d/N]: y Downloading packages: wget-1.14-15.el7_4.1.x86_64.rpm | 547 kB 00:00:00 Running transaction check Running transaction test Transaction test succeeded Running transaction インストール中 : wget-1.14-15.el7_4.1.x86_64 1/1 検証中 : wget-1.14-15.el7_4.1.x86_64 1/1 インストール: wget.x86_64 0:1.14-15.el7_4.1 完了しました!
これでOKです。再度wgetしてみてください
adapter.wsgiを書き換える
先ほど作成したwsgiファイルを書き換えます
# -*- coding:utf-8 -*- import sys, os dirpath = os.path.dirname(os.path.abspath(__file__)) sys.path.append(dirpath) os.chdir(dirpath) import bottle import index application = bottle.default_app()
index.pyファイルを作成
続いてindex.pyファイルを作成します
# coding: utf-8 from bottle import route, run, template from bottle import TEMPLATE_PATH @route('/') def index(): return ("Apacheとbottleの連携成功!") if __name__ == '__main__': run(host='0.0.0.0', port=8081, debug=True, reloader=True)
書いたらApacheの再起動をします
[root@localhost html]# service httpd restart Redirecting to /bin/systemctl restart httpd.service
再起動したらhttp://IPアドレス/にアクセスします。日本語で表示されていたらbottleとの連携成功です
bottleとの連携は成功したので、今度はテンプレートを使ってみます
jinja2を使用
Pythonではテンプレートとしてjinja2が使われるため、これをインストールします
[root@localhost html]# pip install jinja2 Collecting jinja2 Downloading https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl (126kB) 100% |████████████████████████████████| 133kB 2.9MB/s Collecting MarkupSafe>=0.23 (from jinja2) Downloading https://files.pythonhosted.org/packages/08/04/f2191b50fb7f0712f03f064b71d8b4605190f2178ba02e975a87f7b89a0d/MarkupSafe-1.1.0-cp36-cp36m-manylinux1_x86_64.whl Installing collected packages: MarkupSafe, jinja2 Successfully installed MarkupSafe-1.1.0 jinja2-2.10
pipでインストールしました。インストール場所を調べます
[root@localhost html]# pip show jinja2 Name: Jinja2 Version: 2.10 Summary: A small but fast and easy to use stand-alone template engine written in pure python. Home-page: http://jinja.pocoo.org/ Author: Armin Ronacher Author-email: armin.ronacher@active-4.com License: BSD Location: /usr/local/pyenv/versions/3.6.7/lib/python3.6/site-packages Requires: MarkupSafe Required-by:
mod_wsgiと同じところにいました。基本的に同じ階層にいないといけないのでコピーします
[root@localhost html]# cp -R /usr/local/pyenv/versions/3.6.7/lib/python3.6/site-packages/jinja2/ /var/www/html/ [root@localhost html]# ls -all 合計 192 -rw-r--r-- 1 root root 196 11月 1 20:11 adapter.wsgi -rw-r--r-- 1 root root 170188 11月 1 18:58 bottle.py -rw-r--r-- 1 root root 272 11月 1 20:53 index.py drwxr-xr-x 3 root root 4096 11月 1 20:58 jinja2
同じ箇所にもってきました
viewsフォルダを作成
bottleでjinja2を動かす時は、viewsフォルダの中に入れないといけません。ではそこにtop.htmlを作ってみてbottleで読み込んでみたいと思います
[root@localhost html]# mkdir views
top.htmlを作成
[root@localhost html]# cd views/ [root@localhost views]# vi top.html
<!doctype html> <html> <head> <meta charset="utf-8"> <title>無題ドキュメント</title> </head> <body> <h1>Apacheとbottleの連携成功!(HTMLで表示している)</h1> </body> </html>
HTMLの作成はこれで終わりです。
index.pyの修正
index.pyを今度は修正します
# coding: utf-8 from bottle import route, run, template from bottle import TEMPLATE_PATH, jinja2_template as template #jinjaを使うように変えてます @route('/') def index(): return template('top') #topのテンプレートを指定してます if __name__ == '__main__': run(host='0.0.0.0', port=8081, debug=True, reloader=True)
http://IPアドレスにアクセスしてHTMLが表示されていればOKです
終わりに
apacheとPythonの連携はこれで終わりです。nginxを使う予定がない場合はこのままbottleを使っていただければ解決です。次回はフロントにnginxを置いてapacheにリバースプロキシをする方法を紹介します
なぜmod_wsgiをモジュールに持ってきたのか
僕が何度かpyenvとmod_wsgiの連携をしましたが、ことごとく失敗しました。色々調べて行けばいくほど泥沼にはまるようになりました。
yumだと上手くいくけど2.7、pipだと3だけど連携できない。モジュールのロードなのかpythonの読み込みなのかよくわからないという事が続きました。
- apacheのモジュール: /etc/httpd/modules/
- pipでのインストール箇所:/usr/local/pyenv/versions/3.6.7/lib/python3.6/site-packages
とすぐ理解できる人ならpip指定すれば良いなどになりますが、おそらくここまでやってみた人も多くは途中で挫折したりlogwのコードをコピペしても失敗しているかもしれません。
※GCPやほかのクラウドではうまくいかない等考えられるため
混乱でさらにモジュールがどこ?となるよりは、apace関連のモジュールなので同じとこにいれてしまえば、後はそこから読み込めば良いとなります。そのためモジュールをコピーして移動させてます
なぜbottleをpipではなくwgetにしたのか?
bottleも同じで、連携するときに結構四苦八苦しました。pipでインストールしたらどこにでるのか、どこにおけばいいのかなど色々悩みましたが、とあるサイトでbottleは1ファイルだけしかないのでpipとか使うよりwgetで落としてきた方が良いと見ました
実際にwgetで落としてきたら楽だったのでこの方法を採用しました
個人支援・寄付について
サイトラボでは個人支援・寄付を受けております。ご協力いただける方はお願いいたします。当サイトではビットコインで受け付けております。
- ビットコイン:3LHnADwZwUbic2L45EnVJEykiG6KfbqrwS