ひさふぃの日記

DjangoとPythonとLaravelが好き。大阪でフリーランスエンジニアやってます。

CentOS7にpython3を参照するdjango環境を構築

自分なりに構築した際の覚書で、Ansible等で用いるためのメモでもあります。

なお、下記のコマンドは適宜sudoをつけて実行しています。よくわからない場合はrootユーザーでやればいいのですよ。

  • 環境
  • 今回の方針
    • 構成はなるべくシンプルにする。
    • buildするとuninstallが面倒なのでpython3はyumで入れる。
    • wsgiがpython3を参照するようにする。

yumでpython3を入れる

CentOSの標準レポジトリですとpython3が対応していないため、IUSレポジトリを追加します。

追加後、通常のyumコマンドで参照しないようにするために設定のenabledを変更しておきます。

yum install https://centos7.iuscommunity.org/ius-release.rpm  
vi /etc/yum.repos.d/ius.repo   
enabled=1 → enabled=0  

ちなみにこの設定変更はsedコマンドを使うと頭良さそう。しかし、置き換えるファイルの中身を把握する必要があるので、僕が使いこなすのはだいぶ先ですね。

sed -i -e "s/enabled=1/enabled=0/g" "/etc/yum.repos.d/ius.repo"

追加したIUSレポジトリを利用してpython3(今回は3.5.3)を導入します。その後、シンボリックリンクを作成しpython3コマンドで起動できるようにしています。

"python"でpython3にシンボリックリンクを貼るとyumが死ぬので非推奨です。しかし、pyvenvはpython2では使えないコマンドなので、3をつけずに"pyvenv"でシンボリックリンクを作成しています。

yumが死ぬ理由は後で説明しますので、勉強のためにシンボリックリンクを作成するのもありかもしれませんね。

yum --enablerepo=ius install python35u python35u-libs python35u-devel python35u-pip
cd /bin
ln -s python3.5 python3
ln -s pyvenv-3.5 pyvenv

http://www.codeghar.com/blog/install-latest-python-on-centos-7.html
http://weblabo.oscasierra.net/python3-centos7-yum-install/
http://www.server-memo.net/centos-settings/centos7/add-repo.html
https://www.agent-grow.com/self20percent/2016/09/11/centos7にpython3をyumで入れてみます゚д゚/
http://blog.livedoor.jp/hayashikunsan/archives/1001846929.html

仮想環境を作成する

ホームディレクトリに移動して、仮想環境を作成します。

cd
python3 -m venv test_django
. test_django/bin/activate

下のようにユーザー名の左側に括弧で囲まれた文字が出てきましたか?あれば、仮想環境内です。

(test_django) [user@hogehoge hoge]

venv仮想環境内で用いられるpythonのバージョンはvenvを実行したものになります。今回はpython3実行しているので、pip==pip3、python==python3となり同じコマンド扱いです。念のため。

では、djangoをpipで導入してみます。

pip install django
pip freeze
  Django==1.10.5

deactivate
pip3 freeze
  (出力なし)

シンプルでいいですね!

https://docs.python.jp/3/library/venv.html

mod_wsgiを入れてapacheを設定する

yumで入れるとsystemのpython2と紐付くことになるため、python3と紐づけられるpipで入れます。

ただし、いきなりpipで入れようとするとapxsがないよーって言われます。

RuntimeError: The 'apxs' command appears not to be installed or is not executable. Please check the list of prerequisites in the documentation for this package and install any missing Apache httpd server packages.

そこで、先にyumhttpd-develを入れます。

ちなみにpython3導入の際に、"python"のシンボリックリンクをpython3に変える&yumの設定ファイルでpython3を参照するように変更していた場合、yumが死にます。

この時"python"でpython3にシンボリックリンクを貼る弊害に気づき、systemのpython2に戻しました。

yum install http-devel
pip install mod_wsgi

mod_wsgiの場所を探してリンクをコピーして、apacheファイル(wsgi.conf)を作成します。

find / -name "*mod_wsgi*"
  /home/user/test_django/lib/python3.5/site-packages/mod_wsgi/server/mod_wsgi-py35.cpython-35m-x86_64-linux-gnu.so  
  
vi /etc/httpd/conf.d/wsgi.conf 
WSGIScriptAlias /test_wsgi /var/www/html/test_wsgi.py
LoadModule wsgi_module /home/user/django/lib/python3.5/site-packages/mod_wsgi/server/mod_wsgi-py35.cpython-35m-x86_64-linux-gnu.so

apacheが参照している位置にpythonスクリプトを作成します。内容は参照しているpythonのバージョンが表示されるようになっています。

vi /var/www/html/test_wsgi.py 
import sys

def application(environ,start_response):
    status = '200 OK'
    versions = sys.version_info
    output = str(versions).encode('utf-8')
    response_header = [('Content-type','text/plain'),
                        ('Content-Length',str(len(output)))]
    start_response(status,response_header)
    return [output]

apacheを再起動してあげて、設定したアドレスに接続します。

systemctl restart httpd

http://123.456.78.90/test_wsgi

pythonのバージョンがsystemで使用されている2系ではなく、3系が表示されていれば成功!今回の場合はpython3.5.3なので下のように表示されるはずです。

sys.version_info(major=3, minor=5, micro=3, releaselevel='final', serial=0)

http://qiita.com/nekozanmai/items/3ff3d319ff79befa8ce4 http://www.yoheim.net/blog.php?q=20170206 http://tazakazushi.net/apache_no_apxs.html

接続できない時の対処法

何かしらのエラーが出て繋がらない場合は、エラーログを見ることで原因を特定します。

less /var/log/httpd/error_log

エラーとしては、apacheが動いていない、パスの指定を間違えている、pythonモジュールのエラー、ディレクトリのパーミッション辺りを見れば良いようです。

上記で解決しない場合は、centos7特有のメジャーハマりどころ、SELinuxとFirewalld辺りをググると解決するかもしれません。

こんなことを言っておいて、僕は全く違う下記のようなエラーが出てました。結局、エラーログを見るのが大事ということですね。

TypeError: sequence of byte string values expected, value of type str found

http://akiniwa.hatenablog.jp/entry/2013/09/24/150412 http://stackoverflow.com/questions/34838443/typeerror-sequence-of-byte-string-values-expected-value-of-type-str-found

djangoの設定

まず、仮想環境内に入り、djangoでプロジェクトとappsを作成します。

cd

. test_django/bin/activate

cd /var/www/cgi-bin

django-admin startproject test_django

cd test_django

python manage.py startapp apps

ブラウザに表示させるviewsをいじります。これも前回と同じく、djangoが参照しているpythonのバージョンを表示させます。

vi apps/views.py
from django.http import HttpResponse

import sys

def index(request):

     versions = sys.version_info

     output = str(versions).encode('utf-8')

     return HttpResponse(output)

作成したviews.pyをurlに紐づけます。appsとtest_djangoディレクトリ内のurls.pyを作成・編集します。

vi apps/urls.py
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
]
vi test_django/urls.py
from django.conf.urls import url, include

from django.contrib import admin

 

urlpatterns = [

    url(r'^admin/', admin.site.urls),

    url(r'^$', include('apps.urls')),

]

次にwsgi.pyを編集します。仮想環境で使用している設定(site-packages)を参照しますので、パスを探してコピーしておくと楽です。

find / -name "site-packages"
  /home/user/django/lib/python3.5/site-packages

vi test_django/wsgi.py
import os, site, sys

site.addsitedir("/home/user/django/lib/python3.5/site-packages")

sys.path.append("/var/www/cgi-bin/test-django")
sys.path.append("/var/www/cgi-bin/test-django/test-django")

from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_django.settings")

最後に忘れてはいけないのが、設定ファイルのALLOWED_HOSTSです。開発サーバーでは設定しないので見落としがちですが、本番環境では必須項目です。

また、appsをインストールしたことを教えてあげます。

vi test_django/settings.py
ALLOWED_HOSTS = ['123.456.78.90']
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'apps',
]

apacheの設定

前回作成したtest_wsgi.conf(apacheファイル)を読み込まないようにします。末尾のconfを外せばokです。

そして新たにtest_django.confを作成・編集します。先ほどと同様、mod_wsgiのパスを探してコピーしておくと楽です。

mv /etc/httpd/conf.d/test_wsgi.conf /etc/httpd/conf.d/test_wsgi

find / -name "*mod_wsgi*"
  /home/user/django/lib/python3.5/site-packages/mod_wsgi/server/mod_wsgi-py35.cpython-35m-x86_64-linux-gnu.so

vi /etc/httpd/conf.d/test_django.conf
LoadModule wsgi_module /home/user/django/lib/python3.5/site-packages/mod_wsgi/server/mod_wsgi-py35.cpython-35m-x86_64-linux-gnu.so

WSGIPythonPath /var/www/cgi-bin/test_django

WSGIScriptAlias /test_django /var/www/cgi-bin/test_django/test_django/wsgi.py

<Directory /var/www/cgi-bin/test_django/test_django>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

その後、apacheを再起動して、設定したアドレスでpython3系のバージョンが表示されればokです!

systemctl restart httpd

http://123.456.78.90/test_django

sys.version_info(major=3, minor=5, micro=3, releaselevel='final', serial=0)

表示されない場合は、エラーログから原因を特定します。アタリの付け方は同記事の中盤辺りに書いていますので参照してください。

less /var/log/httpd/error_log

表示が確認できたら、デバッグモードをオフにしておきましょう。

vi test_django/settings.py
DEBUG = False

https://docs.djangoproject.com/ja/1.10/intro/tutorial01/ http://akiniwa.hatenablog.jp/entry/2013/09/24/150412 http://stackoverflow.com/questions/40582423/invalid-http-host-header

以上です。この記事が皆さんのお役に立てれば幸いです。