Couldn't load this page.

← ブログ
Engineering

Gunicorn と nginx を使って VPS に Django アプリをデプロイする方法

Yura Oak
Yura Oak2026年8月21日

Django アプリを VPS にデプロイするには、本番用サーバーで実行し、手前にリバースプロキシを置き、データベースを接続して HTTPS を設定します。 このガイドでは Ubuntu 24.04 LTS、Django 5.2、PostgreSQL、Gunicorn、systemd、nginx を使用します。パスとモジュール名は自分のプロジェクトに合わせて調整してください。

SSH と sudo アクセスがある VPS、それを指すドメイン、動作する Django リポジトリ、依存関係のロックまたは固定された requirements.txt が必要です。例ではプレースホルダーとして example.com/srv/myappmyproject.wsgi:application を使用します。対象は WSGI アプリケーションです。アプリで必要な場合は ASGI 構成を使用してください。参照先は 2026年9月9日 に確認しています。

1. サーバーとアプリケーションユーザーを準備する

新しい Ubuntu サーバーに基本パッケージをインストールします:

sudo apt update
sudo apt install -y python3-venv python3-dev build-essential libpq-dev postgresql nginx git
sudo adduser --system --group --home /srv/myapp django
sudo install -d -o django -g django /srv/myapp

django ユーザーは root 権限なしでアプリケーションを実行します。管理用の SSH アクセスは通常のアカウントで維持してください。ファイアウォールのルールを有効にする前に、SSH 接続をファイアウォールで許可し、受信 HTTP と HTTPS を許可してください。PostgreSQL には、アプリが必要とする場所からのみ到達できるようにしてください。

2. PostgreSQL の認証情報を作成する

プロンプトで選んだパスワードでデータベースロールを作成し、そのデータベースを作成します:

sudo -u postgres createuser --pwprompt myapp
sudo -u postgres createdb --owner=myapp myapp

アプリケーションは 127.0.0.1 に接続します。これは通常の Ubuntu の PostgreSQL セットアップではパスワード認証を使用します。接続に失敗する場合は、pg_hba.conf を確認してください。ローカル認証の問題を解決するために、データベースポートを公開しないでください。

3. アプリケーションと依存関係をインストールする

例のリポジトリ URL は置き換えてください。プライベートリポジトリの場合は、URL やコミット済みファイルにトークンを入れずに読み取りアクセスを用意してください。

sudo -u django git clone https://github.com/your-org/your-app.git /srv/myapp/app
sudo -u django python3 -m venv /srv/myapp/venv
sudo -u django /srv/myapp/venv/bin/pip install -r /srv/myapp/app/requirements.txt

requirements には、Django のバージョン、Gunicorn、およびプロジェクトで使用する PostgreSQL ドライバーを含める必要があります。プロジェクトに別の lockfile がある場合は、既存のパッケージマネージャーを使ってください。settings モジュールと WSGI の import パスがリポジトリと一致していることを確認してください。

4. 本番設定を明示的に読み込む

エディタで /etc/myapp.env を作成します。実際の値は Git ではなくそこに保存してください。この例では、settings がこれらの名前を読み取る前提です:

DJANGO_SECRET_KEY='replace-with-a-long-random-secret'
DJANGO_ALLOWED_HOSTS='example.com'
DJANGO_CSRF_TRUSTED_ORIGINS='https://example.com'
DB_NAME='myapp'
DB_USER='myapp'
DB_PASSWORD='replace-with-the-password-you-set'
DB_HOST='127.0.0.1'
DB_PORT='5432'

shell と systemd の environment-file 構文の両方に互換性がある、単純な引用付きの値を使ってください。ファイルを保護します:

sudo chown root:django /etc/myapp.env
sudo chmod 640 /etc/myapp.env

本番 settings では、対応する読み取りを設定します。この断片では、BASE_DIR がすでに存在する前提です:

import os

DEBUG = False
SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
ALLOWED_HOSTS = os.environ['DJANGO_ALLOWED_HOSTS'].split(',')
CSRF_TRUSTED_ORIGINS = os.environ['DJANGO_CSRF_TRUSTED_ORIGINS'].split(',')
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ['DB_NAME'],
        'USER': os.environ['DB_USER'],
        'PASSWORD': os.environ['DB_PASSWORD'],
        'HOST': os.environ['DB_HOST'],
        'PORT': os.environ['DB_PORT'],
    }
}
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'

アップロードされたメディアは、collect した static アセットとは分けてください。アップロードされたコンテンツに応じて、耐久性のあるストレージ、バックアップ方針、アクセス制御を選んでください。Django のデプロイチェックリストを参照してください。

5. 設定を確認し、データベースを準備する

サービスと同じ環境で、アプリユーザーとして管理コマンドを実行します:

sudo -u django bash -c 'set -a; . /etc/myapp.env; set +a; cd /srv/myapp/app; /srv/myapp/venv/bin/python manage.py check --deploy'
sudo -u django bash -c 'set -a; . /etc/myapp.env; set +a; cd /srv/myapp/app; /srv/myapp/venv/bin/python manage.py migrate --noinput'
sudo -u django bash -c 'set -a; . /etc/myapp.env; set +a; cd /srv/myapp/app; /srv/myapp/venv/bin/python manage.py collectstatic --noinput'

デプロイ警告を確認してください。HTTPS 関連の設定は、プロキシで証明書が正しく動作してから行います。既存の本番データベースがある場合は、スキーマ変更を適用する前にバックアップを取得し、テストしてください。マイグレーションは各 Gunicorn worker ではなく、リリースの一部として一度だけ実行してください。

6. systemd 配下で Gunicorn を実行する

/etc/systemd/system/myapp.service を作成します:

[Unit]
Description=Django application
After=network.target postgresql.service

[Service]
User=django
Group=django
WorkingDirectory=/srv/myapp/app
EnvironmentFile=/etc/myapp.env
ExecStart=/srv/myapp/venv/bin/gunicorn myproject.wsgi:application --bind 127.0.0.1:8001 --workers 2 --access-logfile - --error-logfile -
Restart=on-failure
RestartSec=5
PrivateTmp=true
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target

worker 数 2 は初期例であり、サイジングの公式ではありません。増やす前に、メモリ、データベース接続、応答時間を計測してください。Gunicorn は loopback に bind するので、訪問者は nginx 経由でアプリに到達します。

sudo systemctl daemon-reload
sudo systemctl enable --now myapp
sudo systemctl status myapp --no-pager
curl -I -H 'Host: example.com' http://127.0.0.1:8001/

プロセスエラーには journalctl -u myapp を使ってください。通常、import の失敗はモジュールパス、作業ディレクトリ、または依存関係のインストールを示しています。Django の WSGI ガイダンスGunicornを参照してください。

7. 手前に nginx を置く

/etc/nginx/sites-available/myapp を作成します:

server {
    listen 80;
    server_name example.com;

    location /static/ {
        alias /srv/myapp/app/staticfiles/;
    }

    location / {
        proxy_pass http://127.0.0.1:8001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

新しいサイトを一度有効にし、設定をテストしてからリロードします:

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/myapp
sudo nginx -t
sudo systemctl reload nginx

nginx が collect した static ファイルを読み取れ、それらの親ディレクトリをたどれることを確認してください。デフォルトのサイト設定は、他のホスト中ドメインと整合するように保ってください。無関係なサイトを削除しないでください。nginx ガイドでは、リバースプロキシと static ファイルの設定を説明しています。

8. HTTPS を追加し、Django を再確認する

選んだ ACME クライアントとその最新の手順を使って証明書をインストールします。nginx 用に Certbot がインストールされている場合、この例の証明書リクエストは次のとおりです:

sudo certbot --nginx -d example.com
sudo certbot renew --dry-run

OS へのインストールは Certbot の手順を使ってください。TLS の完了と見なす前に、ドメイン DNS、HTTP 到達性、更新を確認してください。

HTTPS が動作したら、これらの Django オプションを設定します:

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

転送プロトコルヘッダーを信頼するのは、nginx がそれを制御し、Gunicorn が直接公開されていないためです。サービスを再起動し、check --deploy を再実行して、HTTPS でログインとフォーム送信をテストしてください。影響を受けるすべてのホストで HTTPS を確認した後に、HSTS は別途確認してください。

9. 今後のリリースを再現可能にする

各リリースでは、レビュー済みのリビジョンを選び、そのロックされた依存関係をインストールし、互換性のあるマイグレーションを適用し、static ファイルを collect し、サービスを再起動してください。ライブアプリケーションをテストし、変更後にエラーを監視してください。

前のリビジョンは利用可能なままにしてください。ただし、コードを戻してもデータベースマイグレーションが元に戻るとは限りません。スキーマ変更の復旧手順を文書化し、別のデータベースへのデータ復元をテストしてください。

アプリが Celery を使う場合は、別のサービス定義、コマンド、broker 設定を用意してください。Gunicorn サービス内で worker をバックグラウンドの shell コマンドとして実行しないでください。

代わりにマネージドホスティングを選ぶべきとき

サーバーを制御したく、自分で保守できるなら VPS は妥当です。ホスト運用をさらに任せたいなら、Python アプリホスティングの選択肢を比較してください。Lizard では、アプリケーションはManaged Postgresと別の worker を使いながら、コードと設定の制御を維持できます。

デプロイドキュメントでは、その方法を扱っています。それでも、正しい Django 設定、リリース手順、検証済みのデータ復旧計画は必要です。

FAQ

なぜ 502 エラーが出るのですか? Gunicorn が実行中で 127.0.0.1:8001 を listen しているか確認し、その後でそのログと nginx の error log を調べてください。リバースプロキシでは、起動に失敗するプロセスは修正できません。

なぜ static ファイルが見つからないのですか? STATIC_ROOTcollectstatic の出力、nginx の alias パス、ファイル権限を確認してください。アップロードされたメディアには別の設定が必要です。

PostgreSQL の代わりに SQLite を使えますか? 使えるアプリケーションもありますが、並行性、永続性、バックアップ要件を評価してください。アプリケーションのワークロードをテストせずにデータベースエンジンを変更しないでください。

デプロイチェックの成功だけで十分ですか? いいえ。実際のユーザーフロー、データベースへの書き込み、ファイルアクセス、復旧をテストしてください。設定チェックで捕捉できるのは本番動作の一部だけです。

AI で構築。Lizard で公開。

本番公開にプラットフォームチームは必要ありません。クラウド全体が、1 つの CLI コマンドですぐ使えます。

無料で試す
ワークスペース
サービス
アドオン
デプロイ

当サイトでは、サイトの基本機能と分析のために Cookie を使用しています。詳細は Cookie ポリシー.