【GeminiとPythonアプリデプロイ】第2章 ApacheとFastCGIの深淵 – .htaccess設定の死闘と光明
Geminiと共に挑むXserver共用サーバーでのPython Flaskアプリケーションデプロイ記、第2章です。
前回(第1章)では、Geminiの提案でFlaskアプリケーション「テキストアナライザー」の骨格を作り上げ、FastCGIでの公開を目指してサーバー設定を開始しました。しかし、Shebangのパス問題、PythonモジュールのModuleNotFoundError
の連鎖(flask
, flup
(実はflup6
パッケージ)、実際には細かいエラーも多数、数々の初期トラブルをGeminiの助けを借りながら一つ一つ解決してきました。
Pythonスクリプト自体はエラーなくインポートされ、FastCGIサーバーとして起動する準備は整ったかに見えました。しかし、ブラウザ経由でアクセスすると、依然としてApacheのエラーログには AH01276: Cannot serve directory ...
や、時には原因不明の404エラーが記録され、アプリケーションは姿を現しません。
今回は、このApacheとFastCGIの連携部分、特に .htaccess
の設定に焦点を当て、なぜリクエストが正しくPythonアプリケーションに届かないのか、その原因究明と解決への試行錯誤を詳述します。
ApacheとFastCGIの壁:.htaccess
設定の迷宮
Pythonスクリプト (main.fcgi
、元 app.fcgi
デバッグ中の切り分けとして名前を変更) の準備は整ったはずなのに、ブラウザからのアクセスがうまくいかない。この問題の核心は、Apacheがリクエストを main.fcgi
に正しくルーティングできていないことにありました。
問題点3:サブディレクトリの .htaccess
が期待通りに機能しない (AH01276
再発)
Gemini:「.htaccess
がApacheに読み込まれていることは確認済みですね(以前の500エラーテストより)。現在のエラー AH01276
は、main.fcgi
がディレクトリのデフォルトハンドラとして認識されていないか、あるいは書き換えルールが機能していないことを示唆しています。Xserverが推奨するFastCGIのハンドラ名 (AddHandler
で指定する値) と記述方法を再確認してください。」
これまでにXserverのサポートへ何度も問い合わせろと言われ続けていたので、無駄だと思いつつ問い合わせることに。
サポートからは「技術的な詳細はサポートできない」ものの、「AddHandler fcgid-script .fcgi
は問題なさそう」という曖昧なコメントを得ました。そこでサブディレクトリ (/apps/text-analyzer/
) に設置した .htaccess
の内容を調整し続けました。
Apache
# /apps/text-analyzer/.htaccess の試行錯誤例
Options +ExecCGI -Indexes
RewriteEngine On
# ハンドラ設定の試行
AddHandler fcgid-script .fcgi
# <Files "main.fcgi">
# SetHandler fcgid-script
# </Files>
# DirectoryIndexの試行
DirectoryIndex main.fcgi
# 書き換えルールの試行
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# RewriteCond %{REQUEST_URI} !/main\.fcgi$ # この行の有無やフラグでエラーが出たりした
RewriteRule ^(.*)$ main.fcgi/$1 [L,QSA]
しかし、ブラウザで /apps/text-analyzer/
にアクセスすると AH01276
が、/apps/text-analyzer/main.fcgi
に直接アクセスすると 404 Not Found
が表示されるという状況が続きました。ルートの .htaccess
(WordPress用) を一時的に無効化しても、この404エラーは解消されませんでした。
ブレイクスルー:超シンプルな test.fcgi
での動作確認
Gemini:「問題が複雑に絡み合っている可能性があります。一旦 main.fcgi
(Flaskアプリ) から離れ、同じディレクトリに、非常にシンプルな内容の test.fcgi
を作成し、同じ .htaccess
設定でこれが動作するか確認しましょう。これで、FastCGI実行環境の基本的な部分が機能しているか切り分けられます。」
本来ならもっと早くにやるべきだと思ってはいたものの、Geminiのデバッグ力を試すために言われるがままにこれまでやってきましたが、この提案に基づき、以下の test.fcgi
を作成しました。
Python
#!/home/takelab/take-lab.com/public_html/apps/text-analyzer/venv/bin/python
# (あるいは /home/takelab/.local/share/uv/python/cpython-3.13.3-.../python3.13 など、最終的に動作したShebang)
# -*- coding: utf-8 -*-
import sys
import os
# (sys.path設定もtest.fcgiにも記述)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
python_version_short = f"python{sys.version_info.major}.{sys.version_info.minor}"
venv_site_packages = os.path.join(BASE_DIR, 'venv', 'lib', python_version_short, 'site-packages')
if os.path.isdir(venv_site_packages):
if venv_site_packages not in sys.path:
sys.path.insert(0, venv_site_packages)
if BASE_DIR not in sys.path:
sys.path.insert(0, BASE_DIR)
def simple_app(environ, start_response):
status = '200 OK'
headers = [('Content-type', 'text/plain; charset=utf-8')]
start_response(status, headers)
return [b"Hello from test.fcgi! This is a simple FastCGI test."]
try:
from flup.server.fcgi import WSGIServer
WSGIServer(simple_app).run()
except Exception as e:
# エラーを stderr に出力 (Apacheエラーログへの記録を期待)
import traceback
sys.stderr.write(f"Error in test.fcgi: {e}\n{traceback.format_exc()}\n")
# FastCGIとして最低限のエラー応答
print("Content-Type: text/plain; charset=utf-8")
print("Status: 500 Internal Server Error")
print()
print("Error in test.fcgi script.")
sys.exit(1)
そして、/apps/text-analyzer/.htaccess
の RewriteRule
のターゲットを test.fcgi
に変更。
Apache
# /apps/text-analyzer/.htaccess (test.fcgi用)
Options +ExecCGI -Indexes
RewriteEngine On
AddHandler fcgid-script .fcgi
DirectoryIndex test.fcgi # DirectoryIndexもtest.fcgiに
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ test.fcgi/$1 [L,QSA] #ターゲットをtest.fcgiに
すると、https://take-lab.com/apps/text-analyzer/test.fcgi
および https://take-lab.com/apps/text-analyzer/
の両方で、「Hello from test.fcgi! This is a simple FastCGI test.」 と表示されました! これは大きな前進です。基本的なFastCGIの実行、.htaccess
によるルーティング(DirectoryIndex
と RewriteRule
の両方)、Shebang、Python仮想環境の認識、flup
の動作が、このシンプルなケースでは問題ないことが確認できました。
問題点4:本番スクリプト main.fcgi
の内容が原因?
test.fcgi
が動作するということは、問題は main.fcgi
のファイル名ではなく、その内容にある可能性が浮上しました。
Gemini:「main.fcgi
の内容を一時的に test.fcgi
と全く同じにしてみてください。それで動作すれば、元の main.fcgi
のコード(Flaskアプリをロードする部分)に、Apacheが実行前にリクエストを404やAH01276として処理してしまう何らかの原因があることになります。」
指示通り、cp test.fcgi main.fcgi
を実行し、main.fcgi
の内容を test.fcgi
と同一にしたところ、https://take-lab.com/apps/text-analyzer/main.fcgi
(および .htaccess
のターゲットを main.fcgi
に戻した上での /apps/text-analyzer/
へのアクセス) で、見事「Hello from test.fcgi!…」が表示されました!
これで、ファイル名や基本的なFastCGI設定ではなく、Flaskアプリケーションをロードする main.fcgi
のスクリプト内容そのものが、Apacheの不可解な挙動(実行前の404やAH01276エラー)を引き起こしていたことがほぼ確定しました。
第3章へ続く。。
ディスカッション
コメント一覧
まだ、コメントがありません