TL;DR
- どうしてもWindows ServerでDjangoアプリを動かす必要がある場合
- gunicornの代わりにWaitressを利用する
- WaitressはVirtualenv環境を参照しないためpip install時に要注意
- WinSWのexeファイルとxmlファイルを組み合わせることで、Windowsサービスとして登録可能
- WinSWとxmlファイルの名称に関して、拡張子以外を一致させることで、xmlの情報を元にWindowsサービスの作成が可能
- gunicornの代わりにWaitressを利用する
- nginxはWindowsバイナリで提供されているけど、ベータ版のため、高いパフォーマンス求められる場合はApacheを利用したほうが良い
目次
記事を書くに至った経緯
- 詳細は書けないのですが、仕事で某製品のソースコードを解析し、イケてないコードを検出するためプロダクトを作りました
- 構成としては以下のような感じで、某製品のexeファイルを用いてXMLファイルを出力する必要があり、Windows Serverでの環境構築が必須でした
- 別途、某製品のXML出力処理を担う処理をラップして、REST APIとして提供するという手もあったのですが、サーバーインスタンスの追加が必要となり、ユーザーの負担費用が増えるため、コストとの兼ね合いで断念しました。
- 記録として残す時間ができたのでアウトプットします。
- ①某製品のソースコードファイル、あるいはアーカイブファイルをアップロード
- ②Celery(タスクキューの仕組み)を利用して、Workerを作成し、某製品のexeファイルをコール
- ③某製品のexeがXMLを出力する
- ④xmlファイルの情報をDBに書き込み
- ⑤後続処理でxmlファイルを解析し、検出したものを情報として記録
DjangoアプリをWindows Serverで動かす
前提
- Djangoプロジェクト名:my_project
- venvなどの仮想環境は利用しない(waitressが仮想環境に対応していないため)
- waitress
Djangoプロジェクトフォルダに移動
$ cd any_folder\my_project
必要なモジュールのインストール
$ pip install waitress $ pip install django # その他必要なモジュール
waitressの起動確認
# my_projectをポート8000で起動する $ waitress-serve X:\any_folder\my_project --port=8000 my_project.wsgi:application
waitressの起動が確認できたらCtrl + Cでwaitressを終了する
WinSWの設定
Winsw-x.x.x-net461.exeをダウンロード github.com
WinSW-x.x.x-net461.exe
をコピー作成し、WinSW-x.x.x-net461_my_project.exe
にリネームする任意の作業ディレクトリに
WinSW-x.x.x-net461_my_project.exe
を配置する- 本例では、
X:\services\waitress
に配置
- 本例では、
上記ディレクトリに
WinSW-x.x.x-net461_my_project.xml
ファイルを作成し、以下の内容を書く
<service> <!-- Windows ID 一意なものを指定すればOK --> <id>my_project.django.waitress.service</id> <!-- Windowsサービス名 --> <name>My Project AP Server</name> <!-- Windowsサービス説明 --> <description>My Project APサーバー(waitress)用のサービスです</description> <executable>waitress-serve</executable> <!-- executableコマンド実行ディレクトリ --> <workingdirectory>X:\any_folder\my_project</workingdirectory> <!-- 実行時の引数 --> <arguments>--port=8000 my_project.wsgi:application</arguments> <logmode>rotate</logmode> </service>
exe及びxml配置後のディレクトリ構成
- X:\services\waitress
- WinSW-x.x.x-net461_my_project.exe
- WinSW-x.x.x-net461_my_project.xml
- X:\services\waitress
Windowsサービスとしてインストール
- 上記作業ディレクトリに移動し、以下のコマンドを実行
- WinSWファイル名.exe installを実行することで、Windowsサービスとして登録できる
$ Winsw-x.x.x-net461_my_project.exe install
- もしアンインストールしたい場合は、uninstallコマンド実行すればOK
$ Winsw-x.x.x-net461_my_project.exe uninstall
Nginxも同様にWinswを利用する
- WinSW-x.x.x-net461.exeをコピー作成し、
Winsw-x.x.x-net461_nginx.exe
にリネーム - xmlファイルを作成:
WinSW-x.x.x-net461_nginx.xml
<service> <id>nginx</id> <name>nginx</name> <description>nginx</description> <logpath>X:\nginx\logs</logpath> <logmode>roll</logmode> <executable>X:\nginx\nginx.exe</executable> <startargument></startargument> <stopexecutable>X:\nginx\nginx.exe</stopexecutable> <stopargument>-s</stopargument> <stopargument>stop</stopargument> </service>
- WinSW-x.x.x-net461_nginx.exe installを実行し、サービス化
個人的にハマったポイント
- Windowsサービス化した後に、個別のexeプログラムが動かない
- サービス登録後に、サービスのプロパティ->ログオンでログインユーザを指定する必要がありました。デフォルトはSYSTEMになっているため、アクセスが制限される可能性があるようです。
- モジュールをインストールしているに、
unable to load celery application the module was not found
のようなエラーが発生する- WaitressがVirtualenv環境を参照しないようです(2022/01時点の情報)
- グローバルのPythonに対してpip installを行う必要があります
その他
普段、pipenvを利用しているので、pipenv syncとかpipenv installで対応しようとして、だいぶハマった気がします。
以下のように、Winswの中で環境変数を定義しても読んでくれなかったので、思考停止したのを思い出しました。今となっては良い思い出です
<!-- --> <env name="VIRTUAL_ENV" value="X:\.virtualenvs\my_project"></env> <env name="PATH" value="%VIRTUAL_ENV%\Scripts;%PATH%"></env>
nginxはWindowsバイナリで提供されていますが、ベータ版のため、 高いパフォーマンス求められる場合はApacheなど、別のミドルウェアを利用したほうが良いらしいです。