XserverにPythion+Flaskのwebアプリをデプロイする手順【Windows10 】

こんにちは、きむらです。
Python+Flaskのwebアプリを、Xserverにデプロイする手順を記載します。
大まかな流れは以下です。

  1. sshでXserverにログイン
  2. pyenvをインストール
  3. Pythonをインストール
  4. Flaskをインストール
  5. アプリを実行

sshでXserver にログイン

Xserverで操作を行うために、sshでサーバーにログインします。

Xserverのサーバーパネルで設定

サーバーパネルにログインして、アカウント欄のSSH設定をクリックします。

SSH設定タブで、「ONにする」を選択して、「設定する」ボタンをタップします。

公開鍵認証用鍵ペアの生成タブにて、「パスフレーズ」を入力し、「確認画面へ進む」ボタンをタップします。

確認画面が表示されるので、「生成する」をタップします。

「公開鍵認証用の鍵ペア生成処理を実行しました。」と画面に表示されて、自動的に秘密鍵のダウンロードが始まり、Downloadフォルダに「サーバーID.key」ファイルが保存されます。

teratermに設定

ターミナルソフトのteratermを使ってSSH接続します。
インストール手順がまだの方は、以下を参考にインストールしてください。

Tera Termの設定は、Xserverの設定マニュアルを見て設定します。公式マニュアルの流れに沿って進めばハマりポイントはありません。ここでは、僕の忘備録として手順を記載しておきます。

ホスト名に、「サーバーID.xsrv.jp」を入力
TCPポートに、「10022」を入力

ユーザー名には、サーバーID
パスフレーズには、公開鍵認証用鍵ペア生成で入力したパスフレーズ
秘密鍵には、ダウンロードした「サーバーID.key」ファイルを指定します。(「id_xserver_rsa.key」にリネームしています。)

Tera Termにプロンプトが表示されて、ログイン完了。

Linuxbrewインストール

ログインした後は、気にせずにinstallすればいい。と思っていたのですが、XserverのSSHログインにはroot権限が設定されていないため、install権限が与えられていないようです。

解決方法は「Linuxbrew」を使用することだそうです。すでに色々と試行錯誤している方がいるので、僕は地雷を回避できるのでありがたいことです。
参考: linuxbrewでエックスサーバーにPythonを導入した話

Linuxbrewの公式サイトを参考に、「Linuxbrew」をインストールします。タームなるから以下のコマンドを1行づつ実行します。

$ sh -c “$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
$ test -d ~/.linuxbrew && eval $(~/.linuxbrew/bin/brew shellenv)
$ test -d /home/linuxbrew/.linuxbrew && eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
$ test -r ~/.bash_profile && echo “eval \$($(brew –prefix)/bin/brew shellenv)" >>~/.bash_profile
$ echo “eval \$($(brew –prefix)/bin/brew shellenv)" >>~/.profile

正直なところ、あまり理解できていないのですが、上記設定を行うと自動的に仮想環境に切り替わるようです。別のシェルで確認したところ、Pythonなどインストールされていなかったので。

Python3インストール

XserverにSSHログインした状態で、ターミナルからLinuxbrewを使って「Python3」をインストールします。

$ brew install python3

Flaskインストール

pip3を使って、「Flask」を仮想環境にインストールします。

$ pip3 install flask

インタプリタを起動し、flaskをimportしてエラーが出なければOK

$ python3
Python 3.7.7 (default, Jun 1 2020, 16:50:29)
[GCC 5.5.0] on linux
Type “help", “copyright", “credits" or “license" for more information.
>>> import flask

Pipenvインストール:Python仮想環境

Python仮想環境を管理できる「Pipenv」をインストールします。

$ pip3 install pipenv

ここまでインストールして、環境を適用します。

$ source ~/.profile

仮想環境を構築

webアプリを置くディレクトリにFlask環境を構築していきます。
htmlなどドメインのhtmlが格納するディレクトリまで移動して、pipenvの環境を作成し、仮想環境に入ります。

$ cd video-collected.com/public_html
$ pipenv install
$ pipenv shell

サンプルファイルで動作確認

Flask公式ドキュメントのサンプルファイルを使用して、構築した環境の動作確認を行います。ブラウザで設定したURLにアクセスし「Hello, World!」と表示されればFlask実行環境は完成です。

このあたりのサイトを参考に構築し、無事に「Hello Wrld」が表示されました。
じつは、表示を出すまでにかなりの試行錯誤がありました。

もしかしたら、同じ悩みを抱える人も多いかもと思ったので、エックスサーバーでFlaskを動かすときに解決した問題について後述します。
なお、完成したソースコードは先に掲載しておきますので、結論だけ欲しい方はどうぞ。

https://video-collected.com/

.htaccess

SetEnvIf Request_URI “." Ngx_Cache_NoCacheMode=off SetEnvIf Request_URI “." Ngx_Cache_StaticMode

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /index.cgi/$1 [QSA,L]

index.cgi

#!/home/サーバーID/.linuxbrew/bin/python3

from wsgiref.handlers import CGIHandler
from hello import app
import os

os.environ['SERVER_NAME’] = “https://video-collected.com/"
os.environ['SERVER_PORT’] = “443"
os.environ['REQUEST_METHOD’] = “GET"

CGIHandler().run(app)

hello.py

#-*– coding: utf-8 –*-

from flask import Flask

app = Flask(name)

@app.route('/’)
def hello_world():
 return “Hello, World!"

パーミッションの設定

公式サイトで指定された通りに設定しています。

.htaccess 644
hello.py  600
index.cgi  755

発生した問題とその対応

次回のTeraTerm接続でコマンドが実行できない【解決済み】

上記設定を行って上手く行ったように見えましたが、後日TeraTermでSSH接続すると、コマンドが全く動かないという現象が発生していました。
そこで、「~/.bash_profile」を次のように変更して、無事?解決しました。

# export PATHeval $(/home/サーバーID/.linuxbrew/bin/brew shellenv)
export PATH
eval $(/home/サーバーID/.linuxbrew/bin/brew shellenv)

なお、以下の表示が出ればインストールは正常に完了だそうです。

$ brew help
Example usage:
brew search [TEXT|/REGEX/]
brew info [FORMULA…]
brew install FORMULA…
brew update
brew upgrade [FORMULA…]
brew uninstall FORMULA…
brew list [FORMULA…]

Troubleshooting:
brew config
brew doctor
brew install –verbose –debug FORMULA

Contributing:
brew create [URL [–no-fetch]]
brew edit [FORMULA…]

Further help:
brew commands
brew help [COMMAND]
man brew
https://docs.brew.sh

500 Internal Server Error【解決済み】

Flask公式のソースコードを上記サイトを参考に配置してみましたが、Internal Server Errorが発生しました。

index.cgiを直接実行で、KeyError: “SERVER_NAME"が発生

python3 index.cgi で、cgiの直接実行を試みたところ、次のエラーが発生

色々試行錯誤してみたところ、環境変数に設定が足りないのでは?と思ってソースコードに追加してみたところ、SERVER_NAMEの問題は解決。他にも出ているので、順次対応し、直接cgi起動は成功です。

flaskのimportでエラーになる

cgiを直接動作させて問題ないのに、なぜかブラウザ経由ではエラーになる。
ブラウザで表示しながらindex.cgiの内容を少しずつコメントアウトしていった結果、flaskのimportが動いて無いことが判明。

直接実行したら動くのになぜだろう。仮想環境で動かしているので実行するpythonが怪しいのではと思って、実行するpythonを変更してみたらビンゴ!
「/usr/bin/python3.6」だとflaskのimportでエラー、pythonで動作する。という違いがありました。

調べて行くと、実行するpythonに問題がありそう。

pythonのシンボリックリンクをたどっていくと、最終的に同じpython 3.7にたどり着く。それでも実行できないのは、flaskのインストールに問題がある可能性が高そう。

flaskのインストールの方法を変更して解決。「pipenv install flask」としていたのがダメだったようだ。
上記の構築手順は修正済み。

実行するpythonがlinuxbrew環境のpathではない

直接CGIを実行すると問題なく動作するんですが、ブラウザ経由で動かすと動作しない。
どうも、実行するpythonにバージョンによって異なるらしい。

$ python index.cgi
Traceback (most recent call last):
File “index.cgi", line 4, in
from hello import app
File “/home/サーバーID/video-collected.com/public_html/hello.py", line 4, in
from flask import Flask
ImportError: No module named flask

$ python3 index.cgi
Status: 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 13

Hello, World!

whichコマンドで実行しているpythonのファイルパスを確認したら、pythonの場合は/usr/bin/pythonになっていた。
「~/.linuxbrew/bin/」は以下にpythonが無いため、標準のpythonをみにいっているようなので、python3と同じファイルにシンボリックリンクを貼ってみます。

$ cd ~/.linuxbrew/bin
$ ln -s ../Cellar/python/3.7.7_1/bin/python3 python

CGIの直接実行は問題なし。だけどブラウザ経由は、あいかわらずの、500 internal Server Errorです。

python パスを相対パスから絶対パスに変更

index.cgiで指定しているpythonパスを相対パスから絶対パスに変更したところ、、500 Internal Server Eroorが解決しました。

https://video-collected.com/

python

Posted by きむら