11.2 Webサーバー
11.2.1 主なWebサーバー
(1) Apache httpd
- 1995年公開のオープンソフトウェア。 NGINXが出てくる前はシェア1位だった
- 開発元は The Apache Software Foundation
- 柔軟な設定、高い拡張性(モジュールによる機能追加)が特徴
- 汎用性が高いので、今でも小規模なWebサイトでは多く使われている
(2) NGINX
- 2004年公開のオープンソフトウェア。現在世界シェア1位
- 高い並行処理性能と低メモリ消費が特徴で、大量のアクセスに強いのが特徴
- NGIXが高速で扱えるのは、基本的に静的ファイルで、 アプリケーションサーバー機能は持っていない
- このため、外部アプリケーションサーバーを用意し、これに処理を引き渡す(リバースプロキシ)構成をとることになる
11.2.2 Apache httpdによるテスト環境の構築
本番環境はLinuxサーバーなどの上に構築することになりますが、まずは、テスト用にApache httpdをmacOS上で使うことにします。想定する構成は以下のとおりです。

11.2.3 Apache httpdのインストール
テストのために、開発マシンであるMacにApache httpdをインストールします。MacにはデフォルトでApache hattpdが組み込まれていますが、macOSのセキュリティ機能により、信頼された署名がない外部モジュールをロードしようとするとエラーが出ます。
djangoを呼び出すのに、mod_wsgiという外部モジュールを使うことになりますが、このデフォルトのhttpdサーバを使うのであれば、自分で「自己署名証明書」を作ってモジュールに署名する必要があり、結構面倒です。そこで、Homebrew版のApache httpdを使うことにします。
まず、標準のApache httpdを停止します。・自動起動を解除します。
# bash
> sudo apachectl stop
標準のApache httpdの自動起動を解除するには、以下のようにします。
# bash
> sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist
HomebrewでApache httpdをインストールします。
# bash
> brew install httpd
インストールが済んだら、試しに起動してみます。
# bash
> sudo brew services start httpd
ここでは、スーパーユーザーとして起動しています。次に停止は以下のようにします。
# bash
> sudo brew servies stop httpd
起動中のアクセス情報やエラー情報は、/opt/homebrew/var/log/httpd/ の下にログ出力されますので、正しく起動停止できているかをこれで確認できます。
11.2.4 拡張モジュールのインストール
最初に説明したように、apache httpdはモジュールを追加して機能を拡充することができます。今回は、mod-wsgiというpythonアプリケーションを実行するための拡張モジュールをインストールして使います。
poetryを使う場合、以下のようにしてインストールします。
# bash
> poetry add mod_wsgi
mod_wsgiのインストールには注意しないといけないことがあります。
実は、macOS向けの事前ビルドされたモジュールは配布されておらず、poetryやpipでインストールを実行すると、PyPIからソースコードがダウンロードされた後に、自動ビルドが行われバイナリーがインストールされる仕組みになっています。このため、ビルドに必要なコンパイラーが必要で、これを事前に用意しておく必要があります。まだインストールしていない場合は、以下を実行してください。コンパイラーを含むXcode Command Line Toolsがインストールされます。
# bash
> xcode-select --install
ビルドされたバイナリファイルの配置場所と、Apache(httpd.conf)に記述すべき設定内容を調べるには、以下のコマンドを実行します。
# bash
> mod_wsgi-express module-config
LoadModule wsgi_module "/Users/kuyamakazuhiro/Seminar/websocket/.venv/lib/python3.14/site-packages/mod_wsgi/server/mod_wsgi-py314.cpython-314-darwin.so"
この出力は、後ほどApache httpdの設定の際に使います。
11.2.5 Apache httpdの設定
Apache httpdは起動時にhttpd.confという設定ファイルを読み込みます。Homebrewでインストールしたhttpdの場合、httpd.confは以下のフォルダにあります。
/opt/homebrew/etc/httpd/
設定ファイルとして、httpd.confが最初に読み込まれますが、ここに他のファイルを設定ファイルとして読み込むように記載することもできます。例えば、以下のようにすると、proxy-html.confが設定ファイルとして読み込まれます。
Include /opt/homebrew/etc/httpd/extra/proxy-html.conf
extra/というフォルダがあり、ここにはオプショナルな設定が記載されている設定ファイルがいくつか入っていますので、これを親のhttpd.confから呼び出して使うこともできます。
(1)httpd.confの設定
httpd.confには基本的な設定だけを行います。元々ついているhttpd.confの雛形に設定されているもの(コメントアウトされているものも含めて)以外は、別ファイルで設定するのが作法になっています。
まず、今回はクライアントから接続されるポートを8080番とするため、Listenの定義を、以下のように8080に設定を行います。
Listen 8080
デフォルトで8080番に設定されている場合は、そのままで大丈夫です。
次に、リバースプロキシを行うために必要なproxyモジュールを組み込みます。モジュールの組み込みはLoadModuleディレクティブを使って行います。元々用意されているhttpd.confには、コメントアウトされた、モジュールの設定が多く含まれています。この中の以下の2行のコメントをはずします。
LoadModule proxy_module lib/httpd/modules/mod_proxy.so
LoadModule proxy_http_module lib/httpd/modules/mod_proxy_http.so
今回は、Apache httpdからDaphneに対しリバースプロキシーでリクエストを転送しますので、これらのモジュールが必要になります。
mod_proxy.soはリバースプロキシーの共通的な仕組みを実現するモジュールで、mod_proxy_http.soは転送先とHTTP(websocket含む)でやり取りを行うモジュールです。mod_proxy_http.soが組み込まれると、その設定ファイル
/opt/homebrew/etc/httpd/extra/proxy-html.conf
が読み込まれます。
そして、djangoやdaphneを呼び出す設定は別ファイルに設定するため、これを呼び出す行を追加します。
Include /opt/homebrew/etc/httpd/extra/httpd-django.conf
(2)django,websocket呼び出し用の設定(httpd-django.conf)
定義ファイルのサンプルを以下に示します。解説はコメントとして書いています。
# httpd-django.conf
#
# Django websocket アプリ (/Users/kuyamakazuhiro/Seminar/websocket)
# /ws/ → Daphne (127.0.0.1:8001) へリバースプロキシー (WebSocket)
# /static/ → 静的ファイル
# それ以外 → mod_wsgi 経由で Django
#
# wsgi用にインストールしたモジュールを組み込む
LoadModule wsgi_module /Users/kuyamakazuhiro/Seminar/websocket/.venv/lib/python3.14/site-packages/mod_wsgi/server/mod_wsgi-py314.cpython-314-darwin.so
# デーモンモード(Apacheのプロセスとは別のプロセスで動作する)になっているアプリケーションへのリクエストのみを許可する。
# デーモンモードで動作しない設定になっているアプリケーションへのリクエストは全てエラーにする。
WSGIRestrictEmbedded On
# WSGIアプリケーション(ここではdjango)をデーモンモードで動かすための設定をいます。django_daemonという名前をつけて
# 設定します。
# Apacheの埋め込みモードではなく、独立したプロセスでPythonアプリを動作させ、安定性やパフォーマンスを向上させます。
# sudo で起動した場合も、プロジェクトの所有者として動かす (db.sqlite3 への書き込みのため)
# user group: 通常、Apache httpdはsudo を使って起動され、_wwwユーザの権限で実行されます。
# この場合デーモンプロセスも_wwwユーザの権限で実行されdb.sqlite3に書き込みができなくなることがあるため、
# 自分のユーザー権限で動くように設定しています。postgreSQLを使う場合はここは省略しても構いません。
# processes threads: WSGIデーモンが1プロセスあたり5スレッドで動作し、そのプロセスを1つだけ起動するよう設定しています。
# Djangoは同時に最大5件のリクエストを処理でき、6件目以降は、どれかのスレッドが空くまで待たされます。
# stack-size: macOS のスレッド既定スタック(512KB)では Python 3.14 が
# Django の import 中に RecursionError になるため 8MB にする
WSGIDaemonProcess django_daemon \
user=kuyamakazuhiro group=staff \
python-home=/Users/kuyamakazuhiro/Seminar/websocket/.venv \
python-path=/Users/kuyamakazuhiro/Seminar/websocket \
processes=1 threads=5 \
stack-size=8388608
# リクエストをどのプロセスグループで処理するかを指定します。
WSGIProcessGroup django_daemon
WSGIApplicationGroup %{GLOBAL}
# WebSocket で Daphne へリクエスト転送するための設定
# ProxyPreserveHostはブラウザが送ってきた Host ヘッダーをそのまま渡すための設定です。
# これをoffにしていると、ヘッダーのHostは127.0.0.1:8001(ProxyPass に書いた転送先)になってしまいます。
ProxyPreserveHost On
# ProxyPassはクライアントからのリクエストを、バックエンド(内部)のWebサーバーに転送します
# websocketへの対応するため、upgrade=websocketを設定します。
# クライアントから何も通信が来なかった場合に接続を切断するタイムアウト秒を3600(1時間)に設定します。
ProxyPass /ws/ http://127.0.0.1:3000/ws/ upgrade=websocket timeout=3600
# ProxyPassReverseはバックエンドサーバーから返されるHTTPレスポンスのリダイレクト用ヘッダー
#(LocationやContent-Locationなど)を書き換えます。
ProxyPassReverse /ws/ http://127.0.0.1:3000/ws/
# 静的ファイル
Alias /static/ /Users/kuyamakazuhiro/Seminar/websocket/staticfiles/
<Directory /Users/kuyamakazuhiro/Seminar/websocket/staticfiles>
Require all granted
</Directory>
# それ以外は Django (mod_wsgi) へ渡す
# /で始まるURLを持つリクエスト(つまり全て)リクエストを、指定した WSGI スクリプト(Django の wsgi.py)に
# 処理させます。ただし、/ws/(ProxyPass)と /static/(Alias)は、それぞれの設定が先に処理するので、
# ここには来ません。
WSGIScriptAlias / /Users/kuyamakazuhiro/Seminar/websocket/websocket/wsgi.py
# wsgi.pyファイルへのアクセスを許可します。
#(Apache httpd側から見て、アクセスが必要なのはwsgi.pyのみ。それ以外のファイルに直接アクセスすることはない)
<Directory /Users/kuyamakazuhiro/Seminar/websocket/websocket>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
11.2.6 daphneの起動
Daphneの実行モジュールは、.venv/binの下にインストールされているはずです。ローカルでポート3000番で起動するために、以下のようなオプションをつけて起動します。
# bash
> daphne -b 127.0.0.1 -p 3000 websocket.asgi:application