気ままなタンス*プログラミングなどのノートブック

プログラミングやRPGツクール、DTM等について、学んだことや備忘録をアウトプットとして残し、情報を必要としている誰かにとって「かゆいところに手が届く」ブログとなることを願いながら記事を書いています。

【Django】Windows ServerでDjangoアプリをサービスとして動かす(Winsw+Waitress+Nginx)

スポンサーリンク

TL;DR

  • どうしてもWindows ServerでDjangoアプリを動かす必要がある場合
    • gunicornの代わりにWaitressを利用する
      • WaitressはVirtualenv環境を参照しないためpip install時に要注意
    • WinSWのexeファイルとxmlファイルを組み合わせることで、Windowsサービスとして登録可能
      • WinSWとxmlファイルの名称に関して、拡張子以外を一致させることで、xmlの情報を元にWindowsサービスの作成が可能
  • nginxはWindowsバイナリで提供されているけど、ベータ版のため、高いパフォーマンス求められる場合はApacheを利用したほうが良い

目次

記事を書くに至った経緯

  • 詳細は書けないのですが、仕事で某製品のソースコードを解析し、イケてないコードを検出するためプロダクトを作りました
  • 構成としては以下のような感じで、某製品のexeファイルを用いてXMLファイルを出力する必要があり、Windows Serverでの環境構築が必須でした
    • 別途、某製品のXML出力処理を担う処理をラップして、REST APIとして提供するという手もあったのですが、サーバーインスタンスの追加が必要となり、ユーザーの負担費用が増えるため、コストとの兼ね合いで断念しました。
  • 記録として残す時間ができたのでアウトプットします。

f:id:rinne_grid2_1:20220313190558p:plain

  • ①某製品のソースコードファイル、あるいはアーカイブファイルをアップロード
  • ②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
  • 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になっているため、アクセスが制限される可能性があるようです。

f:id:rinne_grid2_1:20220313184850p:plain

  • モジュールをインストールしているに、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など、別のミドルウェアを利用したほうが良いらしいです。

nginx.org