Elastic Compute Service (ECS) インスタンス上で、静的ファイルの配信に Nginx を、アプリケーションプロセスの管理に uWSGI を使用して Django プロジェクトをデプロイできます。このアーキテクチャは動的コンテンツと静的コンテンツを分離することで、サービスのパフォーマンスを向上させます。
仕組み
ブラウザーがサーバーに HTTP または HTTPS リクエストを送信します。
フロントエンドサーバーとして動作する Nginx が、受信リクエストを受け取ります。
静的ファイル (CSS、JavaScript、画像など) へのリクエストは、Nginx が直接配信します。これにより応答速度が向上し、Django アプリケーションへの負荷が低減します。
動的リクエストは uWSGI サーバーへ転送されます。
uWSGI は Nginx からのリクエストを Django アプリケーションに中継し、ワーカープロセスを管理することでリクエストを分散させます。
Django アプリケーションはビジネスロジック (データベースのクエリやテンプレートのレンダリングなど) を処理し、uWSGI にレスポンスを返します。
操作手順
ステップ 1: リソースの準備
ECS インスタンスを作成します。
インスタンス購入ページに移動します。[カスタム購入] タブを選択します。
インスタンスタイプ:vCPU 2 以上、メモリ 4 GiB 以上のインスタンスを使用します。
イメージ: Alibaba Cloud Linux 3。
ネットワークとセキュリティグループ:
ネットワーク:作成した VPC を選択します。
パブリック IP:[パブリック IPv4 アドレスを割り当てる] を選択します。
セキュリティグループ: [新規セキュリティグループ] を選択し、[HTTP (TCP: 80)] を選択します。
ランタイム環境を設定します。
Nginx と Python 開発ツールをインストールし、uWSGI をコンパイルできるようにします。
デフォルトリポジトリの Nginx バージョンは古く、セキュリティリスクが生じる可能性があります。最新の安定版をインストールするために、公式 Nginx リポジトリを追加してください。
# 公式 Nginx リポジトリをシステムに追加します。 sudo tee /etc/yum.repos.d/nginx.repo <<-'EOF' [nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/8/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key module_hotfixes=true EOF sudo yum install -y python3.8 python38-devel pcre-devel gcc make nginx # Django と uWSGI をインストールします。 sudo python3.8 -m pip install --upgrade pip wheel -i https://mirrors.aliyun.com/pypi/simple sudo python3.8 -m pip install "Django>=4.2,<5.0" "uwsgi>=2.0.23" -i https://mirrors.aliyun.com/pypi/simpleログ、静的ファイル、メディアファイルをそれぞれ格納するための
logs、static、mediaディレクトリと、ソケットファイルを格納するための/run/uwsgiディレクトリを作成します。sudo mkdir -p /srv/django-app/{logs,static,media} sudo mkdir -p /run/uwsgi
ステップ 2: Django アプリケーションのデプロイ
サンプルの Django プロジェクトを作成します。
プロジェクトごとに依存関係を分離し、プロジェクト間のパッケージバージョンの競合を避けるため、Python 仮想環境を作成することを推奨します。
sudo /usr/local/bin/django-admin startproject myproject /srv/django-app/本番環境のセキュリティとパフォーマンスの要件を満たすため、プロジェクトの設定ファイル
/srv/django-app/myproject/settings.pyを変更します。DEBUG属性をFalseに設定します。これにより、アプリケーションエラーが発生した際に機密情報やコードの詳細が漏洩するのを防ぎます。ALLOWED_HOSTS属性をインスタンスのパブリック IP アドレスに設定します。このリストが空の場合、アプリケーションは起動できません。これは Django の組み込みセキュリティ対策です。IP アドレスは文字列としてリストに含める必要があります。例:
['xxx.xxx.xxx.xxx']ファイルの末尾に
STATIC_ROOT = BASE_DIR / 'static'を追加し、静的ファイルのディレクトリを指定します。
サンプルプロジェクトの静的ファイルを
STATIC_ROOTで指定したディレクトリに収集し、Nginx が直接アクセスできるようにします。sudo python3.8 /srv/django-app/manage.py collectstatic --noinputデータベース移行を実行して、ユーザー情報などのアプリケーションデータを格納するテーブルスキーマを作成します。
デフォルトでは、Django プロジェクトは SQLite3 を使用しますが、これは本番環境には適していません。
myproject/settings.pyファイルのDATABASES設定を変更することで、別のデータベースに置き換えることができます。sudo python3.8 /srv/django-app/manage.py migrate後で Django 管理パネルにログインするため、プロジェクトの管理者アカウントを作成します。
sudo python3.8 /srv/django-app/manage.py createsuperuser
ステップ 3: uWSGI サービスの設定
/etc/django-app.iniに uWSGI 構成ファイルを作成します。プロジェクトのパス、プロセスモデル、ソケットファイルの場所、ログファイルを指定します。processesパラメーターは、インスタンスの CPU コア数に基づいて調整してください。コア数 * 2に設定することを推奨します。非特権ユーザーとしてサービスを実行することを推奨します。これにより、アプリケーションが侵害された場合でも攻撃者が root アクセス権を取得できないようにします。
[uwsgi] # プロジェクト設定 chdir = /srv/django-app module = myproject.wsgi:application # プロセス設定 master = true processes = 4 threads = 2 # ネットワークと権限の設定 socket = /run/uwsgi/django-app.sock chmod-socket = 666 chown-socket = root:root vacuum = true # セキュリティとランタイムの設定 uid = root gid = root die-on-term = true # ログ設定 logto = /srv/django-app/logs/uwsgi.loguWSGI サービスをバックグラウンドで起動します。
ps aux | grep uwsgiコマンドを実行して uWSGI のプロセス状態を確認できます。nohup /usr/local/bin/uwsgi --ini /etc/django-app.ini &(任意) OS 起動時に uWSGI サービスが自動起動するように設定し、サービスの信頼性を高めるために、systemd でサービスを管理します。
起動ファイル
/etc/systemd/system/uwsgi-django-app.serviceを次のスクリプトで作成します。[Unit] Description=uWSGI service for Django App After=network.target [Service] User=root Group=root RuntimeDirectory=uwsgi ExecStart=/usr/local/bin/uwsgi --ini /etc/django-app.ini Restart=always KillSignal=SIGQUIT Type=notify NotifyAccess=all [Install] WantedBy=multi-user.targetuWSGI サービスを起動し、起動時に有効化します。
sudo systemctl daemon-reload sudo systemctl start uwsgi-django-app sudo systemctl enable uwsgi-django-appサービスの状態を確認します。
sudo systemctl status uwsgi-django-app
ステップ 4: Nginx をフロントエンドサーバーとして設定
以下の内容をNginx の設定ファイル
/etc/nginx/conf.d/django-app.confとして保存します。その際、<server_ip>をインスタンスのパブリック IP アドレスに置き換えてください。# uWSGI ソケットファイルを指す upstream を定義します。 upstream django_backend { server unix:/run/uwsgi/django-app.sock; } server { listen 80; server_name <server_ip>; # パブリック IP アドレスに置き換えてください。 charset utf-8; client_max_body_size 20M; # 静的ファイルサービス location /static/ { alias /srv/django-app/static/; } # メディアファイルサービス location /media/ { alias /srv/django-app/media/; } # 他のすべてのリクエストを Django アプリケーションにプロキシします。 location / { include /etc/nginx/uwsgi_params; uwsgi_pass django_backend; } }nginx -tコマンドを実行して、Nginx の設定ファイルを検証します。出力に
syntax is okとtest is successfulが含まれていれば、構成は有効です。Nginx を再起動して新しい構成を適用し、起動時に有効化します。
sudo systemctl restart nginx sudo systemctl enable nginxhttp://<ECS インスタンスのパブリック IP アドレス>/adminでサンプルプロジェクトのログインページにアクセスします。
本番運用時の注意点
非特権ユーザーとしてサービスを実行:ログイン権限のないシステムユーザーを作成してアプリケーションを実行します。これにより権限が分離され、サーバーのセキュリティが強化されます。アプリケーションコードの脆弱性が悪用された場合でも、攻撃者は root アクセス権を取得できません。
# ログイン権限のないシステムユーザー (django-app) を作成します。 sudo useradd --system --shell /bin/false --home /srv/django-app django-app # アプリケーションディレクトリの所有権を django-app ユーザーに変更します。 sudo chown -R django-app:django-app /srv/django-appPython 仮想環境を使用:各プロジェクトに個別の Python 仮想環境を作成し、依存関係を分離してパッケージバージョンの競合を回避します。これにより、デプロイ環境がよりクリーンで予測可能になり、再現しやすくなります。
# 仮想環境を作成します。 python3.8 -m venv venv # 仮想環境を有効化します。 source venv/bin/activate
トラブルシューティング
502 Bad Gateway エラー
このエラーは通常、Nginx が uWSGI と正常に通信できないことを示します。
systemctl status uwsgi-django-appで uWSGI サービスの状態を確認します。tail -f /srv/django-app/logs/uwsgi.logで uWSGI ログを確認します。ls -l /run/uwsgi/django-app.sockでソケットファイルの存在とその権限を確認します。
静的ファイルアクセス時の 403 Forbidden エラー
この問題は、Nginx プロセスが静的ファイルディレクトリを読み取る権限がないために発生します。
Nginx を実行しているユーザー (Alibaba Cloud Linux では通常
nginx) が、/srv/django-app/static/ディレクトリとそのすべてのサブディレクトリおよびファイルに対する読み取り (r) と実行 (x) 権限を持っていることを確認してください。
500 Internal Server Error
このエラーは、Django アプリケーションで内部エラーが発生したことを示します。
問題を特定するには、デバッグモードを一時的に有効にします。プロジェクトの設定ファイル
settings.pyでDEBUGをTrueに変更し、uWSGI サービスを再起動してからページを再読み込みしてください。ブラウザに問題を特定する詳細なスタックトレースが表示されます。重要これはデバッグ目的でのみ行ってください。問題を解決した後、機密情報の漏洩を防ぐために
DEBUGをFalseに戻してください。uWSGI ログを確認します。エラーは uWSGI ログファイルにも記録されます。ログを参照して、Django で発生した具体的なエラーを見つけます。