annyoung

Ubuntu Apache wsgi with Python3.7.5, Flask and Virtualenv 본문

카테고리 없음

Ubuntu Apache wsgi with Python3.7.5, Flask and Virtualenv

nopsled 2020. 1. 11. 17:43

Devops 삽질기...

 

wsgi로 sys.version을 출력한 결과

위 이미지를 보면 아무것도 안한 상태의 Ubuntu Apache는 wsgi python을 2.7.x로 로드한다.

 

현재 주어진 개발 환경은 3.7.x의 virtualenv를 사용해야 하므로 3.7.x로 컴파일된 wsgi를 사용해야 한다.

wget https://github.com/GrahamDumpleton/mod_wsgi/archive/4.6.5.tar.gz
tar xvf 4.6.5.tar.gz
cd mod_wsgi-4.6.5
./configure --with-python=/usr/bin/python3.7
make
make install

configure에서 Python.h가 없다고 에러가 나는 경우엔 apt-get install python3.7-dev를 하도록 한다.

 

설치가 완료되면 모듈의 경로를 알려준다

wsgi가 설치 되었으므로 이제 apache.conf에 LoadModule을 넣어줄 차례다.

 

/etc/apache2/apache.conf의 맨 마지막 줄에 LoadModule wsgi_module /usr/lib/apache2/modules/mod_wsgi.so 를 추가 하도록한다.

 

추가한 후에 VirtualHost를 추가해줘야 하므로 /etc/apache2/sites-available로 이동한다.

 

필자는 ssl을 적용시킬 예정이므로 다음과 같이 000-default.conf를 수정하도록 하겠다.

 

 

SSL Redirection을 사용하는 경우

# 000-default.conf
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName localhost
    ServerAlias localhost.com
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =www.localhost.com [OR]
    RewriteCond %{SERVER_NAME} =localhost.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

localhost를 자신의 도메인으로 수정하도록 한다.

 

#default-ssl.conf

<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerAdmin webmaster@localhost
    ServerName localhost
    ServerAlias localhost
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLCertificateFile /etc/letsencrypt/live/mysite/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/mysite/privkey.pem

    WSGIDaemonProcess myapp user=www-data group=www-data threads=5
    WSGIScriptAlias / /var/www/onland/app.wsgi
    Alias /static/ /var/www/onland/app/static/
    <Directory /var/www/onland>
        WSGIProcessGroup myapp
        WSGIApplicationGroup %{GLOBAL}
       Order allow,deny
       Allow from all
   </Directory>
</VirtualHost>
</IfModule>

 

 

SSL Redirection을 사용하지 않는 경우

# 000-default.conf

<IfModule mod_ssl.c>
<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName localhost
    ServerAlias localhost
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    WSGIDaemonProcess myapp user=www-data group=www-data threads=5
    WSGIScriptAlias / /var/www/onland/app.wsgi
    Alias /static/ /var/www/onland/app/static/
    <Directory /var/www/onland>
        WSGIProcessGroup myapp
        WSGIApplicationGroup %{GLOBAL}
       Order allow,deny
       Allow from all
   </Directory>
</VirtualHost>
</IfModule>

 

현재 프로젝트의 디렉토리 구조

onland
├── app
│   ├── __pycache__
│   ├── admin
│   │   └── __pycache__
│   ├── api
│   │   ├── __pycache__
│   │   └── parser
│   │       ├── MonthlySeries
│   │       │   └── __pycache__
│   │       ├── WeeklySeries
│   │       │   └── __pycache__
│   │       └── __pycache__
│   ├── login
│   │   └── __pycache__
│   ├── main
│   │   └── __pycache__
│   ├── register
│   │   └── __pycache__
│   ├── static
│   │   ├── css
│   │   └── js
│   └── templates
│   └── __init__.py
├── assets
│   ├── js
│   └── sass
├── app.wsgi
└── myapp.py

전체적인 디렉토리 흐름인데 내 프로젝트의 경우 app.wsgi가 myapp을 참조하고 myapp은 app 디렉토리의 __init__.py에서 create_app 함수를 가져와 app 객체를 생성한다. 더 쉽게 보고싶다면 https://github.com/miguelgrinberg/flasky를 확인해보면 알기 쉬울 것이다.

 

# app.wsgi
import sys
sys.path.insert(0, '/var/www/onland')

python_home = '/var/www/onland/virtualenv'
activate_this = python_home + '/bin/activate_this.py'
with open(activate_this) as file_:
    exec(file_.read(), dict(__file__=activate_this))

from myapp import app as application

app.wsgi는 위와같이 넣어주면된다.

1~2번 라인은 환경변수를 집어넣어주고.

4~7번 라인은 virtualenv의 경로를 집어 넣어주는 부분이다.

9번 라인은 myapp라는 python 파일에서 app 객체를 import 하고 application이라고 로드한다. (wsgi 규약상 무조건 application라고 써야한다.)

 

# virtualenv/bin/activate_this.py
import sys
import site

python_home = '/var/www/onland/virtualenv'
python_version = '.'.join(map(str, sys.version_info[:2]))
site_packages = python_home + '/lib/python%s/site-packages' % python_version
site.addsitedir(site_packages)

prev_sys_path = list(sys.path)
site.addsitedir(site_packages)
new_sys_path = []

for item in list(sys.path):
    if item not in prev_sys_path:
        new_sys_path.append(item)
        sys.path.remove(item)

sys.path[:0] = new_sys_path

app.wsgi에서 activate_this.py라는 virtualenv wrapper를 실행하도록 되어 있는데 위 행동은 환경 변수에 virtualenv site-packages를 추가해주는 역할을 한다.

 

# myapp.py
from app import create_app
app = create_app()

myapp.py는 app 디렉토리의 __init__.py에서 create_app 함수를 가져와 Flask app 객체를 리턴받는다. 

 

# app/__init__.py
import os
from flask import Flask
from flask_restful import Api

def create_app():
    app = Flask(__name__)
    app.secret_key = '1234' or os.urandom(24)

    api = Api(app)

    # Add login views
    from .login import login as login_blueprint
    app.register_blueprint(login_blueprint)
    
    from .api import Login, Register, Logout
    api.add_resource(Login, '/api/login')
    api.add_resource(Register, '/api/register')
    api.add_resource(Logout, '/logout')
    return app

위에서 언급한 미구엘씨가 작성한 flasky를 보면서 디렉토리 구조를 이해하면 훨씬 보기 편하다.

 

위와 같이 설정이 끝나면 service apache2 restart를 날려주면 적용 끝.

 

 

혹시나 안된다면 댓글을 달아주세요. 해결 해드리도록 하겠습니다.

Please add comment on this post when you got some errors.

Comments