[Python] Windowsサーバ(IIS)でDjangoアプリを公開する

##この記事について

IISでDjangoを動かす方法を作業手順にまとめました。

確認環境：
Windows Server 2016(Azure VM) / Windows 7
Python 3.6.4
Django 2.0.5

## 前提知識

IISでDjangoを動かすには、Microsoftの提供しているIIS-Python接続モジュール「[wfastcgi](https://pypi.org/project/wfastcgi/)」を利用します。まずはwfastcgiの公式サイトをよく読んで設定方法を確認してください。

wfastcgi公式：https://pypi.org/project/wfastcgi/

### 必要環境

- Windows 2008 R2/Windows7 Professional 以上。
- IIS 7.5 以上が設定済みでCGIを有効化している
- Python をインストール済み
- 要インターネット接続

CGIの有効化方法：https://technet.microsoft.com/ja-jp/library/ff454027.aspx

### この記事での設定

|||
|:--|:--|
|Djangoプロジェクト名|myproject
|公開サイト|Default Web Site|
|公開サイトルート物理パス  |C:\inetpub\wwwroot\myproject|

公開サイトは新規に作成したサイトでもＯＫです。
**注意：wfastcgiの仕様上、既存の公開サイト内にプロジェクトを設置することは出来ません。**

IIS環境を本番環境として使う場合は、設定ファイルの以下の設定についても変更を検討してください。

- DEBUG
- ALLOWED_HOSTS
- DATABASES
- SECURE_PROXY_SSL_HEADER

## ディレクトリ構成

最終的なディレクトリ構成は以下の通りとなります。

```
C:
└─inetpub
    └─wwwroot
        └─myproject          # プロジェクトのディレクトリ（公開サイトの物理ルートパス）
            │ web.config     # メインディレクトリ用設定ファイル
            ├─env            # virtualenv 仮想環境ディレクトリ
            └─static         # 静的ファイルディレクトリ（管理コマンド collectstatics で作成する）
                └web.config  # 静的ファイルディレクトリ用設定ファイル
```


## 作業手順


### 手順１．プロジェクトのディレクトリを配置する

まずwwwroot直下にプロジェクトのディレクトリを手動コピー、もしくはGitコマンド等で配置します。

### 手順２．仮想環境を作る

プロジェクト直下に移動し、仮想環境を作成します。

```cmd
cd c:\inetpub\wwwroot\myproject
python -m venv env
```

作成後、仮想環境をアクティベートしてパッケージのインストールを行います。(requirements.txtは作成済みとする)

```cmd
env\Scripts\activate
pip install -r requirements.txt
```

**※ 以降のコマンドはすべて仮想環境下で実行する**

### 手順３．wfastcgiを有効化する。

追加でwfastcgiのパッケージをインストールします。

```cmd
pip install wfastcgi
```

インストール後、wfastcgiのコマンドでIISにwfastcgiを登録します。

```
env\Scripts\wfastcgi-enable.exe
```

この時出力された文字列は、この次のweb.configの作成時に使うのでエディタ等に張り付けておきます。

```
(env) C:\inetpub\wwwroot\myproject>env\Scripts\wfastcgi-enable.exe
構成変更を構成コミット パス "MACHINE/WEBROOT/APPHOST" の "MACHINE/WEBROOT/APPHOST" のセクション "sys
tem.webServer/fastCgi" に適用しました
"c:\inetpub\wwwroot\myproject\env\scripts\python.exe|c:\inetpub\wwwroot\myproject\env\lib\site-packa
ges\wfastcgi.py" can now be used as a FastCGI script processor
```


wfastcgiの登録状況はIISマネージャより確認できます。

[確認場所]：サーバーの管理グループ：IIS FastCGIの設定

### 手順４．web.config を作成する。

IISの設定ファイル「web.config」を作成します。

まず以下のコマンドを実行し、web.configの中でhandlersセクションが利用できるように制限を解除します。

``` cmd
%windir%\system32\inetsrv\appcmd unlock config -section:system.webServer/handlers

(env) C:\inetpub\wwwroot\myproject>%windir%\system32\inetsrv\appcmd unlock config -section:system.we
bServer/handlers
構成パス "MACHINE/WEBROOT/APPHOST" のセクション "system.webServer/handlers" のロックを解除しました。
```

この設定の状態はIISマネージャより確認することができます。

[確認場所]：サーバーの管理グループ：構成エディタ⇒セクション：system.webServer/handlers⇒右側：操作メニューで「セクションのロック」が表示されていればアンロック状態

次にプロジェクト内`c:\inetpub\wwwroot\myproject`に新規ファイル`web.config`を作成し、以下の内容を貼り付けます。

```xml:myproject\web.config
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <appSettings>
    <add key="WSGI_HANDLER" value="django.core.wsgi.get_wsgi_application()" />
    <add key="PYTHONPATH" value="C:\inetpub\wwwroot\myproject" />
    <add key="DJANGO_SETTINGS_MODULE" value="myproject.settings" />
  </appSettings>
  <system.webServer>
    <handlers>
        <add name="Python FastCGI" path="*" verb="*" modules="FastCgiModule" scriptProcessor="c:\inetpub\wwwroot\myproject\env\scripts\python.exe|c:\inetpub\wwwroot\myproject\env\lib\site-packages\wfastcgi.py" resourceType="Unspecified" />
    </handlers>
  </system.webServer>
</configuration>

```

- PYTHONPATH はプロジェクトのディレクトリを指定します。
- DJANGO_SETTINGS_MODULE はプロジェクトルートからsettings.pyまでのパスを指定します。
- scriptProcessorには、先ほどの`wfastcgi-enable.exe`の実行時に出力された文字列を指定します。

ファイルを保存後、以下のコマンドでDefault Web Site の物理パスをプロジェクトのディレクトリに変更します。

```cmd
%windir%\system32\inetsrv\appcmd set vdir "Default Web Site/" -physicalPath:"c:\inetpub\wwwroot\myproject"
```

これはIISの構成マネージャからでも設定・確認可能です。

[確認方法]：Default Web Site の基本設定（右ペイン）⇒物理パス

設定後にブラウザで「http://loclhost」 にアクセスしましょう。
CSS、画像ファイルの無い状態でトップ画面が表示されるはずです。

[注意]データベースエラーが出る場合は、settings.pyのデータベース設定が正しいか確認しましょう。

### 手順５．静的ファイルの構成

開発時のサーバ `manage.py runserver` とは異なり、静的ファイルはIISの機構を使って公開します。



まずはsettings.pyに以下の静的ファイルの集積先の指定を追加します。

```py:settings.py
STATIC_ROOT = 'C:\inetpub\wwwroot\myproject\static'
```

次に以下のコマンドを実行してください。

```cmd
cd c:\inetpub\wwwroot\myproject
manage.py collectstatic
```

実行後、プロジェクトのディレクトリに`static`という名前のフォルダが作成され、中に各アプリケーションの静的ファイルが集積されます。次に、このstaticフォルダの中に先ほどとは別の`web.config`を作成します。

web.configは上位ディレクトリの設定が自動的に有効になるので、このままでは静的ファイルへのリクエストもDjangoへのリクエストと認識されてしまいます。通常のファイルへのリクエストとして認識させるため、上位のweb.configの影響を解除する設定を行います。


```xml:myproject\static\web.config

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <remove name="Python FastCGI" />
    </handlers>
  </system.webServer>
</configuration>
```

ファイルを保存後、再度ブラウザより「http://loclhost」 にアクセスしましょう。完全な状態でトップ画面が表示されれば成功です。


### 初回、または長時間放置後にアクセスしたときに処理が重い場合

以下の対応を行うと改善します。

- アプリケーションプールの「開始モード」を「AlwaysRunning」する
- WEBサイトの「有効化されたプリロード」を「True」にする

※ただし、この設定はIIS8.0以降にしかないので注意。7.5では追加モジュールで対応できるらしい。

[参考] https://docs.microsoft.com/en-us/iis/get-started/whats-new-in-iis-8/iis-80-application-initialization

### wwwroot下にプロジェクトを置かない構成方法

今回の構成ではリクエストはすべてCGIが中継するのでプロジェクトのファイルが外部に見えてしまうことはありませんが、wwwroot外にプロジェクトのファイルを配置することも普通に可能です。その場合今回の記事の作業に加えて以下の作業が必要になります。

- プロジェクトおよび仮想環境のディレクトリに対して IIS_USRSユーザーの参照・実行権限を付与する

- プロジェクトルートに`templates`ディレクトリを追加している場合は、手動で公開ディレクトリにコピーする

- [注意] wfastcgiには、開発環境サーバのようにファイルの修正を検知して自動的に再起動を行うオートリスタート機能がありますが、このようにwwwroot配下にファイルを置かない構成では機能しません。


## 参考
- [メモ的な思考的な：Windows7 + IIS + virtualenv + wfastcgiで、Djangoをホストする](http://thinkami.hatenablog.com/entry/2015/10/26/070118)

- [Qiita：Python(Django) をWindows+IISで動かす](https://qiita.com/Kashq/items/14491e1da28bd953ee4c)