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環境にする予定です。

手順

基本的には以下の手順になります

  1. Apacheのインストール
  2. Python(pyenv)のインストール
  3. pipの設定
  4. Apache+Pythonの連携←ここ
  5. 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) 
`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で落としてきたら楽だったのでこの方法を採用しました