DigitalOceanマネージドデータベースとスペースを使用してスケーラブルなDjangoアプリをセットアップする方法
序章
Django は、PythonアプリケーションまたはWebサイトをすばやく立ち上げるのに役立つ強力なWebフレームワークです。 これには、オブジェクトリレーショナルマッパー、Python API、アプリケーション用のカスタマイズ可能な管理インターフェイスなど、いくつかの便利な機能が含まれています。 また、キャッシングフレームワークが含まれており、URLディスパッチャーおよびテンプレートシステムを通じてクリーンなアプリの設計を促進します。
箱から出してすぐに、Djangoにはテストとローカル開発用の最小限のWebサーバーが含まれていますが、本番ユースケース用のより堅牢なサービングインフラストラクチャと組み合わせる必要があります。 Djangoは、静的ファイルリクエストとHTTPSリダイレクトを処理するためのNginxウェブサーバーと、アプリを提供するための GunicornWSGIサーバーとともに展開されることがよくあります。
このガイドでは、JavascriptやCSSスタイルシートなどの静的ファイルをDigitalOcean Spacesにオフロードし、オプションでCオンテントD配信
前提条件
このガイドを開始する前に、次のものを利用できるようにしておく必要があります。
- 基本的なファイアウォールと非rootユーザーを備えた新しいUbuntu18.04サーバーインスタンス
sudo
構成された特権。 Ubuntu 18.04を使用した初期サーバーセットアップを実行することで、これをセットアップする方法を学ぶことができます。 - DigitalOceanマネージドPostgreSQLクラスター。 クラスタの作成方法については、DigitalOcean管理対象データベースの製品ドキュメントを参照してください。
- Djangoプロジェクトの静的ファイルとこのスペースのアクセスキーのセットを保存するDigitalOceanスペース。 スペースの作成方法については、スペースの作成方法の製品ドキュメントを参照してください。また、スペースのアクセスキーの作成方法については、アクセスキーを使用したスペースへのアクセスの共有を参照してください。
- Nginxは、選択したドメイン名で動作するようにサーバーにインストール、保護、および構成されています。 Let’s Encrypt を使用したAレコードの設定とNginxインストールの保護の詳細については、 Ubuntu18.04でLet’sEncryptを使用してNginxを保護する方法を参照してください。
ステップ1—Ubuntuリポジトリからパッケージをインストールする
まず、Ubuntuリポジトリから必要なすべてのアイテムをダウンロードしてインストールします。 Pythonパッケージマネージャーを使用します pip
少し後で追加のコンポーネントをインストールします。
最初にローカルを更新する必要があります apt
パッケージインデックスを作成し、パッケージをダウンロードしてインストールします。
このガイドでは、 Python3でDjangoを使用します。 必要なライブラリをインストールするには、サーバーにログインして次のように入力します。
- sudo apt update
- sudo apt install python3-pip python3-dev libpq-dev curl postgresql-client
これによりインストールされます pip
、Gunicornのビルドに必要なPython開発ファイル、 Pyscopg PostgreSQL Pythonアダプターのビルドに必要なlibpqヘッダーファイル、およびPostgreSQLコマンドラインクライアント。
打つ Y
その後 ENTER
パッケージのダウンロードとインストールを開始するように求められたら。
次に、Djangoアプリで動作するようにデータベースを構成します。
ステップ2—PostgreSQLデータベースとユーザーを作成する
次に、Djangoアプリケーション用のデータベースとデータベースユーザーを作成します。
まず、クラウドコントロールパネルからデータベースに移動し、データベースをクリックして、クラスターの接続パラメーターを取得します。 クラスタのいくつかのパラメータを含む接続の詳細ボックスが表示されます。 これらを書き留めてください。
コマンドラインに戻り、これらの資格情報と psql
インストールしたばかりのPostgreSQLクライアント:
- psql -U username -h host -p port -d database -set=sslmode=require
プロンプトが表示されたら、Postgresユーザー名の横に表示されているパスワードを入力し、 ENTER
.
データベースを管理できるPostgreSQLプロンプトが表示されます。
まず、プロジェクトのデータベースを作成します。 polls
:
- CREATE DATABASE polls;
注:すべてのPostgresステートメントはセミコロンで終了する必要があるため、問題が発生している場合は、コマンドがセミコロンで終了していることを確認してください。
これで、に切り替えることができます polls
データベース:
- \c polls;
次に、プロジェクトのデータベースユーザーを作成します。 安全なパスワードを選択してください。
- CREATE USER myprojectuser WITH PASSWORD 'password';
次に、作成したユーザーの接続パラメーターのいくつかを変更します。 これにより、データベース操作が高速化されるため、接続が確立されるたびに正しい値を照会して設定する必要がなくなります。
デフォルトのエンコーディングをに設定しています UTF-8
、Djangoが期待しています。 また、デフォルトのトランザクション分離スキームを「読み取りコミット」に設定しています。これは、コミットされていないトランザクションからの読み取りをブロックします。 最後に、タイムゾーンを設定します。 デフォルトでは、Djangoプロジェクトは使用するように設定されます UTC
. これらはすべて、Djangoプロジェクト自体からの推奨事項です。
PostgreSQLプロンプトで次のコマンドを入力します。
- ALTER ROLE myprojectuser SET client_encoding TO 'utf8';
- ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';
- ALTER ROLE myprojectuser SET timezone TO 'UTC';
これで、新しいユーザーに新しいデータベースを管理するためのアクセス権を与えることができます。
- GRANT ALL PRIVILEGES ON DATABASE polls TO myprojectuser;
終了したら、次のように入力してPostgreSQLプロンプトを終了します。
- \q
これで、Djangoアプリがこのデータベースに接続して管理する準備が整いました。
次のステップでは、インストールします virtualenv
Djangoプロジェクト用のPython仮想環境を作成します。
ステップ3—プロジェクト用のPython仮想環境を作成する
アプリケーションで動作するようにデータベースを設定したので、このプロジェクトの依存関係をシステムのグローバルPythonインストールから分離するPython仮想環境を作成します。
これを行うには、最初ににアクセスする必要があります virtualenv
指図。 これをインストールできます pip
.
アップグレード pip
次のように入力してパッケージをインストールします。
- sudo -H pip3 install --upgrade pip
- sudo -H pip3 install virtualenv
と virtualenv
インストールすると、Python仮想環境を保存するディレクトリを作成し、Djangoで使用できるようになります。 polls
アプリ。
と呼ばれるディレクトリを作成します envs
それにナビゲートします:
- mkdir envs
- cd envs
このディレクトリ内に、というPython仮想環境を作成します polls
次のように入力します。
- virtualenv polls
これにより、というディレクトリが作成されます polls
以内 envs
ディレクトリ。 内部には、Pythonのローカルバージョンとのローカルバージョンがインストールされます pip
. これを使用して、プロジェクト用に分離されたPython環境をインストールおよび構成できます。
プロジェクトのPython要件をインストールする前に、仮想環境をアクティブ化する必要があります。 次のように入力すると、次のように入力できます。
- source polls/bin/activate
プロンプトが変化して、Python仮想環境内で操作していることを示します。 次のようになります。 (polls)user@host:~/envs$
.
仮想環境をアクティブにして、Django、Gunicorn、および psycopg2
ローカルインスタンスが pip
:
注:仮想環境がアクティブ化されたとき(プロンプトが (polls)
その前に)、使用する pip
それ以外の pip3
、Python3を使用している場合でも。 ツールの仮想環境のコピーには常に名前が付けられます pip
、Pythonのバージョンに関係なく。
- pip install django gunicorn psycopg2-binary
これで、Djangoを実行するために必要なすべてのソフトウェアが揃うはずです。 polls
アプリ。 次のステップでは、Djangoプロジェクトを作成し、このアプリをインストールします。
ステップ4—PollsDjangoアプリケーションを作成する
これで、サンプルアプリケーションを設定できます。 このチュートリアルでは、DjangoドキュメントのPollsデモアプリケーションを使用します。 これは、ユーザーが投票を表示して投票できる公開サイトと、管理者が投票を変更、作成、および削除できる管理コントロールパネルで構成されています。
このガイドでは、チュートリアルの手順をスキップし、DigitalOceanコミュニティ django-pollsrepoから最終的なアプリケーションのクローンを作成します。
手順を手動で完了する場合は、次のディレクトリを作成します。 django-polls
ホームディレクトリに移動し、そこに移動します。
- cd
- mkdir django-polls
- cd django-polls
そこから、公式のDjangoドキュメントから最初のDjangoアプリの作成チュートリアルに従うことができます。 完了したら、ステップ5にスキップします。
完成したアプリのクローンを作成するだけの場合は、ホームディレクトリに移動して使用します git
django-polls repo のクローンを作成するには:
- cd
- git clone https://github.com/do-community/django-polls.git
cd
その中に、ディレクトリの内容を一覧表示します。
- cd django-polls
- ls
次のオブジェクトが表示されます。
OutputLICENSE README.md manage.py mysite polls templates
manage.py
アプリを操作するために使用されるメインのコマンドラインユーティリティです。 polls
が含まれています polls
アプリコード、および mysite
プロジェクトスコープのコードと設定が含まれています。 templates
管理インターフェイス用のカスタムテンプレートファイルが含まれています。 プロジェクトの構造とファイルの詳細については、Djangoの公式ドキュメントからプロジェクトの作成を参照してください。
アプリを実行する前に、デフォルト設定を調整してデータベースに接続する必要があります。
ステップ5—アプリの設定を調整する
このステップでは、Djangoプロジェクトのデフォルト構成を変更してセキュリティを強化し、Djangoをデータベースに接続して、静的ファイルをローカルディレクトリに収集します。
テキストエディタで設定ファイルを開くことから始めます。
- nano ~/django-polls/mysite/settings.py
を見つけることから始めます ALLOWED_HOSTS
指令。 これは、Djangoインスタンスへの接続に使用するアドレスまたはドメイン名のリストを定義します。 このリストにないHostヘッダーを持つ着信要求は、例外を発生させます。 Djangoでは、特定のクラスのセキュリティ脆弱性を防ぐために、これを設定する必要があります。
角かっこ内に、Djangoサーバーに関連付けられているIPアドレスまたはドメイン名をリストします。 各項目は、エントリをコンマで区切って引用符で囲む必要があります。 リストには次のものも含まれます localhost
、ローカルNginxインスタンスを介して接続をプロキシするため。 ドメイン全体とサブドメインのリクエストを含める場合は、エントリの先頭にピリオドを追加します。
以下のスニペットには、これらのエントリがどのように表示されるかを示すコメントアウトされた例がいくつかあります。
. . .
# The simplest case: just add the domain name(s) and IP addresses of your Django server
# ALLOWED_HOSTS = [ 'example.com', '203.0.113.5']
# To respond to 'example.com' and any subdomains, start the domain with a dot
# ALLOWED_HOSTS = ['.example.com', '203.0.113.5']
ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . ., 'localhost']
. . .
次に、データベースアクセスを構成するファイルのセクションを見つけます。 それはで始まります DATABASES
. ファイル内の構成はSQLiteデータベース用です。 プロジェクト用にPostgreSQLデータベースをすでに作成しているため、これらの設定を調整する必要があります。
Djangoに使用するように指示します psycopg2
インストールしたデータベースアダプタ pip
、デフォルトのSQLiteエンジンの代わりに。 また、ステップ2で参照されている接続パラメータを再利用します。 この情報は、DigitalOceanクラウドコントロールパネルの管理対象データベースセクションからいつでも見つけることができます。
データベース設定でファイルを更新します:データベース名(polls
)、データベースユーザー名、データベースユーザーのパスワード、およびデータベース host
と port
. データベース固有の値を独自の情報に置き換えてください。
. . .
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'polls',
'USER': 'myprojectuser',
'PASSWORD': 'password',
'HOST': 'managed_db_host',
'PORT': 'managed_db_port',
}
}
. . .
次に、ファイルの一番下に移動し、静的ファイルを配置する場所を示す設定を追加します。 これは、Nginxがこれらのアイテムのリクエストを処理できるようにするために必要です。 次の行は、Djangoにそれらをというディレクトリに配置するように指示しています static
ベースプロジェクトディレクトリ:
. . .
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
終了したら、ファイルを保存して閉じます。
この時点で、Djangoプロジェクトのデータベース、セキュリティ、静的ファイルの設定を構成しました。 あなたが従った場合 polls
チュートリアルを最初から行い、GitHubリポジトリのクローンを作成しなかった場合は、ステップ6に進むことができます。 GitHubリポジトリのクローンを作成した場合、追加の手順が1つ残っています。
Django設定ファイルには SECRET_KEY
さまざまなDjangoオブジェクトのハッシュを作成するために使用される変数。 一意の予測できない値に設定することが重要です。 The SECRET_KEY
変数はGitHubリポジトリからスクラブされているため、組み込みの関数を使用して新しい変数を作成します。 django
と呼ばれるPythonパッケージ get_random_secret_key()
. コマンドラインから、Pythonインタープリターを開きます。
- python
次の出力とプロンプトが表示されます。
OutputPython 3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
をインポートします get_random_secret_key
Djangoパッケージから関数を作成し、関数を呼び出します。
- from django.core.management.utils import get_random_secret_key
- get_random_secret_key()
結果のキーをクリップボードにコピーします。
を押してPythonインタープリターを終了します CTRL+D
.
次に、テキストエディタで設定ファイルをもう一度開きます。
nano ~/django-polls/mysite/settings.py
を見つけます SECRET_KEY
変数を作成し、生成したキーを貼り付けます。
. . .
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'your_secret_key_here'
. . .
ファイルを保存して閉じます。
次に、Django開発サーバーを使用してアプリをローカルでテストし、すべてが正しく構成されていることを確認します。
ステップ6—アプリをテストする
Django開発サーバーを実行する前に、 manage.py
データベーススキーマを作成し、静的ファイルを収集するユーティリティ STATIC_ROOT
ディレクトリ。
プロジェクトのベースディレクトリに移動し、PostgreSQLデータベースに初期データベーススキーマを作成します。 makemigrations
と migrate
コマンド:
- cd django-polls
- ./manage.py makemigrations
- ./manage.py migrate
makemigrations
Djangoモデルに加えられた変更に基づいて、移行またはデータベーススキーマの変更を作成します。 migrate
これらの移行をデータベーススキーマに適用します。 Djangoでの移行の詳細については、Djangoの公式ドキュメントのMigrationsを参照してください。
次のように入力して、プロジェクトの管理ユーザーを作成します。
- ./manage.py createsuperuser
ユーザー名を選択し、メールアドレスを入力し、パスワードを選択して確認する必要があります。
次のように入力して、構成したディレクトリの場所にすべての静的コンテンツを収集できます。
- ./manage.py collectstatic
静的ファイルは、次のディレクトリに配置されます。 static
プロジェクトディレクトリ内。
サーバーの初期設定ガイドに従った場合は、サーバーを保護するUFWファイアウォールが必要です。 開発サーバーをテストするには、使用するポートへのアクセスを許可する必要があります。
ポートの例外を作成する 8000
次のように入力します。
- sudo ufw allow 8000
Django開発サーバーを使用したアプリのテスト
最後に、次のコマンドでDjango開発サーバーを起動して、プロジェクトをテストできます。
- ./manage.py runserver 0.0.0.0:8000
Webブラウザーで、サーバーのドメイン名またはIPアドレスにアクセスし、その後にアクセスします。 :8000
そしてその polls
道:
- http://server_domain_or_IP:8000/polls
Pollsアプリのインターフェースが表示されます。
管理インターフェースを確認するには、サーバーのドメイン名またはIPアドレスにアクセスしてから、 :8000
および管理インターフェースのパス:
- http://server_domain_or_IP:8000/admin
Pollsアプリの管理者認証ウィンドウが表示されます。
で作成した管理ユーザー名とパスワードを入力します createsuperuser
指図。
認証後、Pollsアプリの管理インターフェースにアクセスできます。
探索が終了したら、 CTRL-C
ターミナルウィンドウで、開発サーバーをシャットダウンします。
Gunicornを使用したアプリのテスト
静的ファイルをオフロードする前に最後に実行したいのは、Gunicornをテストして、アプリケーションにサービスを提供できることを確認することです。 これを行うには、プロジェクトディレクトリに入り、 gunicorn
プロジェクトのWSGIモジュールをロードするには:
- gunicorn --bind 0.0.0.0:8000 mysite.wsgi
これにより、Django開発サーバーが実行されていたのと同じインターフェースでGunicornが起動します。 戻ってアプリをもう一度テストできます。
注: Gunicornはこれに関与する静的CSSコンテンツを見つける方法を知らないため、管理インターフェースにはスタイルが適用されません。
Djangoへの相対ディレクトリパスを指定して、Gunicornにモジュールを渡しました。 wsgi.py
ファイル、アプリケーションへのエントリポイント。 このファイルは、と呼ばれる関数を定義します application
、アプリケーションと通信します。 WSGI仕様の詳細については、ここをクリックをクリックしてください。
テストが終了したら、 CTRL-C
ターミナルウィンドウでGunicornを停止します。
次に、アプリケーションの静的ファイルをDigitalOceanSpacesにオフロードします。
ステップ7—静的ファイルをDigitalOceanスペースにオフロードする
この時点で、GunicornはDjangoアプリケーションを提供できますが、静的ファイルは提供できません。 通常、これらのファイルを提供するようにNginxを構成しますが、このチュートリアルでは、django-storagesプラグインを使用してそれらをDigitalOceanSpacesにオフロードします。 これにより、静的コンテンツを一元化し、サーバーリソースを解放することで、Djangoを簡単にスケーリングできます。 さらに、DigitalOceanSpacesCDNを使用してこの静的コンテンツを配信できます。
Django静的ファイルをオブジェクトストレージにオフロードするための完全なガイドについては、Djangoを使用してオブジェクトストレージをセットアップする方法を参照してください。
インストールと構成 django-storages
まず、インストールします。 django-storages
Pythonパッケージ。 The django-storages
パッケージはDjangoに S3Boto3Storage
を使用するストレージバックエンド boto3
S3互換のオブジェクトストレージサービスにファイルをアップロードするためのライブラリ。
開始するには、django-storages
と boto3
を使用したPythonパッケージ pip
:
- pip install django-storages boto3
次に、アプリのDjango設定ファイルをもう一度開きます。
- nano ~/django-polls/mysite/settings.py
下に移動します INSTALLED_APPS
ファイルのセクション、および追加 storages
インストールされているアプリのリストへ:
. . .
INSTALLED_APPS = [
. . .
'django.contrib.staticfiles',
'storages',
]
. . .
ファイルをさらに下にスクロールして、 STATIC_URL
以前に変更しました。 これらの値を上書きして、新しい値を追加します S3Boto3Storage
バックエンドパラメータ。 以前に入力したコードを削除し、スペースのアクセスと場所の情報を含む次のブロックを追加します。 ここで強調表示されている値を独自の情報に置き換えることを忘れないでください::
. . .
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
AWS_ACCESS_KEY_ID = 'your_spaces_access_key'
AWS_SECRET_ACCESS_KEY = 'your_spaces_secret_key'
AWS_STORAGE_BUCKET_NAME = 'your_space_name'
AWS_S3_ENDPOINT_URL = 'spaces_endpoint_URL'
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
AWS_LOCATION = 'static'
AWS_DEFAULT_ACL = 'public-read'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATIC_URL = '{}/{}/'.format(AWS_S3_ENDPOINT_URL, AWS_LOCATION)
STATIC_ROOT = 'static/'
次の構成項目を定義します。
AWS_ACCESS_KEY_ID
:チュートリアルの前提条件で作成したスペースのアクセスキーID。 アクセスキーのセットを作成しなかった場合は、アクセスキーを使用したスペースへのアクセスの共有を参照してください。AWS_SECRET_ACCESS_KEY
:DigitalOceanSpaceの秘密鍵。AWS_STORAGE_BUCKET_NAME
:DigitalOceanSpaceの名前。AWS_S3_ENDPOINT_URL
:オブジェクトストレージサービスへのアクセスに使用されるエンドポイントURL。 DigitalOceanの場合、これは次のようになりますhttps://nyc3.digitaloceanspaces.com
スペースリージョンによって異なります。AWS_S3_OBJECT_PARAMETERS
静的ファイルにキャッシュ制御ヘッダーを設定します。AWS_LOCATION
:すべての静的ファイルが配置されるオブジェクトストレージバケット内のディレクトリを定義します。AWS_DEFAULT_ACL
:静的ファイルのアクセス制御リスト(ACL)を定義します。 に設定するpublic-read
エンドユーザーがファイルに公的にアクセスできるようにします。STATICFILES_STORAGE
:Djangoが静的ファイルをオフロードするために使用するストレージバックエンドを設定します。 このバックエンドは、DigitalOceanSpacesを含むすべてのS3互換バックエンドで動作するはずです。STATIC_URL
:静的ファイルのURLを生成するときにDjangoが使用するベースURLを指定します。 ここでは、エンドポイントURLと静的ファイルサブディレクトリを組み合わせて、静的ファイルのベースURLを作成します。STATIC_ROOT
:静的ファイルをオブジェクトストレージにコピーする前に、ローカルで収集する場所を指定します。
編集が完了したら、ファイルを保存して閉じます。
これから、走ると collectstatic
、Djangoはアプリの静的ファイルをSpaceにアップロードします。 Djangoを起動すると、このスペースからCSSやJavascriptなどの静的アセットの提供が開始されます。
次のセクションでは、このSpaceのCDNを有効にし、オプションでSpacesCDNのカスタムサブドメインを構成します。 これにより、地理的に分散したエッジサーバーのネットワーク全体にキャッシュすることで、Djangoプロジェクトの静的ファイルの配信が高速化されます。 CDNの詳細については、CDNを使用した静的コンテンツ配信の高速化を参照してください。 Spaces CDNを有効にしたくない場合は、CORSヘッダーの設定に進んでください。
CDNの有効化(オプション)
DigitalOcean Spaces CDNを介した静的ファイル配信をアクティブ化するには、まずDigitalOceanSpaceのCDNを有効にします。 これを行う方法については、DigitalOcean製品ドキュメントの SpacesCDNを有効にする方法を参照してください。
Spaces CDNでカスタムドメインを使用する場合は、サブドメインでSpaces CDNエンドポイントをカスタマイズする方法に従って、サブドメインCNAMEレコードと適切なSSL証明書を作成します。
SpacesCDNでカスタムドメインを使用することを強くお勧めします。 これにより、オフロードされたアセットのURLをDjangoサイトのURLと同様に保つことで、サイトの検索エンジン最適化(SEO)が大幅に向上します。 Spaces CDNでカスタムドメインを使用するには、最初にドメインをDigitalOceanアカウントに追加する必要があります。 これを行う方法については、ドメインを追加する方法を参照してください。
スペースのCDNを有効にし、オプションでそのカスタムサブドメインを作成したら、クラウドコントロールパネルを使用してスペースに移動します。 スペース名の下に新しいEndpointsリンクが表示されます。
これらのエンドポイントには、スペース名が含まれている必要があります。 Spaces CDNのカスタムサブドメインを作成した場合、このリストにはサブドメインという追加のエンドポイントが含まれます。
Edge エンドポイントは、SpacesオブジェクトのリクエストをCDN経由でルーティングし、可能な限りエッジキャッシュからそれらを提供します。 このEdgeエンドポイントを書き留めてください。これを使用して、 django-storages
プラグイン。 Spaces CDNのサブドメインを作成した場合、SubdomainエンドポイントはこのEdgeエンドポイントのエイリアスです。
次に、アプリのDjango設定ファイルをもう一度編集します。
- nano ~/django-polls/mysite/settings.py
最近変更した[静的ファイル]セクションに移動します。 追加します AWS_S3_CUSTOM_DOMAIN
を構成するためのパラメーター django-storages
プラグインCDNエンドポイントと更新 STATIC_URL
この新しいCDNエンドポイントを使用するためのパラメーター:
. . .
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
# Moving static assets to DigitalOcean Spaces as per:
# how-to-set-up-object-storage-with-django
AWS_ACCESS_KEY_ID = 'your_spaces_access_key'
AWS_SECRET_ACCESS_KEY = 'your_spaces_secret_key'
AWS_STORAGE_BUCKET_NAME = 'your_space_name'
AWS_S3_ENDPOINT_URL = 'spaces_endpoint_URL'
AWS_S3_CUSTOM_DOMAIN = 'spaces_edge_endpoint_URL'
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
AWS_LOCATION = 'static'
AWS_DEFAULT_ACL = 'public-read'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATIC_URL = '{}/{}/'.format(AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)
STATIC_ROOT = 'static/'
ここで、 spaces_edge_endpoint_URL
書き留めたばかりのEdgeエンドポイントを使用して、 https://
プレフィックス。 たとえば、エッジエンドポイントURLが https://example.sfo2.cdn.digitaloceanspaces.com
, AWS_S3_CUSTOM_DOMAIN
次のように設定する必要があります example.sfo2.cdn.digitaloceanspaces.com
.
カスタムサブドメインを作成した場合は、 spaces_edge_endpoint_URL
カスタムサブドメインエンドポイントを使用して、 https://
プレフィックス。 たとえば、サブドメインのエンドポイントURLが https://assets.example.com
, AWS_S3_CUSTOM_DOMAIN
次のように設定する必要があります assets.example.com
.
完了したら、ファイルを保存して閉じます。
Djangoを起動すると、DigitalOceanSpaceのCDNを使用して静的コンテンツが提供されるようになります。
これがすべて正しく機能していることをテストする前に、Spacesファイルの Cross-Origin Resource Sharing(CORS)ヘッダーを構成する必要があります。そうしないと、特定の静的アセットへのアクセスがWebブラウザーによって拒否される場合があります。 Djangoで使用されているのと同じドメインに対してSpacesCDNでカスタムサブドメインを使用している場合は、 Spaces Static FileDeliveryのテストに進んでください。
CORSヘッダーの設定
CORSヘッダーは、あるドメインで実行されているアプリケーションが別のドメインにあるスクリプトまたはリソースにアクセスできることをWebブラウザーに通知します。 この場合、スペース内の静的ファイルのリクエストがWebブラウザーによって拒否されないように、Djangoサーバーのドメインのクロスオリジンリソース共有を許可する必要があります。
注:この手順は、SpacesCDNでカスタムサブドメインを使用していない場合にのみ必要です。
まず、クラウドコントロールパネルを使用して、スペースの設定ページに移動します。
CORS構成セクションで、追加をクリックします。
ここで、 Origin の下に、ワイルドカードの原点を入力します。 *
警告:アプリを本番環境にデプロイするときは、必ずこの値を正確な元のドメイン( http://
また https://
プロトコル)。 ワイルドカードオリジンとしてこれを残すことは安全ではありません。オリジンをhttp://example.com:8000(非標準ポートを使用)に設定することは現在サポートされていないため、ここではテスト目的でのみこれを行います。
許可されたメソッドで、GETを選択します。
ヘッダーの追加をクリックし、表示されるテキストボックスに次のように入力します Access-Control-Allow-Origin
.
アクセス制御の最大経過時間をに設定します 600
作成したヘッダーが10分ごとに期限切れになるようにします。
[オプションの保存]をクリックします。
今後、スペース内のオブジェクトには適切なものが含まれます Access-Control-Allow-Origin
応答ヘッダー。最新の安全なWebブラウザーがドメイン間でこれらのファイルをフェッチできるようにします。
テストスペースの静的ファイル配信
ここで、DjangoがDigitalOceanSpaceから静的ファイルを正しく提供していることをテストします。
Djangoアプリディレクトリに移動します。
- cd ~/django-polls
ここから、実行します collectstatic
静的ファイルを収集してDigitalOceanSpaceにアップロードするには:
- python manage.py collectstatic
次の出力が表示されます。
OutputYou have requested to collect static files at the destination
location as specified in your settings.
This will overwrite existing files!
Are you sure you want to do this?
Type 'yes' to continue, or 'no' to cancel:
タイプ yes
とヒット ENTER
確認するために。
次のような出力が表示されます。
Output121 static files copied.
これは、Djangoが正常にアップロードしたことを確認します polls
静的ファイルをスペースに適用します。 クラウドコントロールパネルを使用してスペースに移動し、 static
ディレクトリ。
次に、Djangoが適切なURLを書き換えていることを確認します。
Gunicornサーバーを起動します。
- gunicorn --bind 0.0.0.0:8000 mysite.wsgi
Webブラウザーで、サーバーのドメイン名またはIPアドレスにアクセスし、その後にアクセスします。 :8000
と /admin
:
http://server_domain_or_IP:8000/admin
もう一度、Pollsアプリの管理者認証ウィンドウが表示されます。今回は正しいスタイルで表示されます。
次に、ブラウザの開発者ツールを使用して、ページの内容を調べ、ソースファイルの保存場所を明らかにします。
Google Chromeを使用してこれを行うには、ページを右クリックして、検査を選択します。
次のウィンドウが表示されます。
ここから、ツールバーのソースをクリックします。 左側のペインのソースファイルのリストに、次のように表示されます。 /admin/login
Djangoサーバーのドメインの下で、 static/admin
SpaceのCDNエンドポイントの下。 内部 static/admin
、両方が表示されるはずです css
と fonts
ディレクトリ。
これにより、CSSスタイルシートとフォントがSpaceのCDNから正しく提供されていることが確認されます。
テストが終了したら、 CTRL-C
ターミナルウィンドウでGunicornを停止します。
次のように入力すると、アクティブなPython仮想環境を無効にできます deactivate
:
- deactivate
プロンプトは通常に戻るはずです。
この時点で、Djangoサーバーから静的ファイルを正常にオフロードし、オブジェクトストレージからそれらを提供しています。 これで、システムサービスとして自動的に開始するようにGunicornを構成することに進むことができます。
ステップ8—Gunicorn用のsystemdソケットおよびサービスファイルの作成
ステップ6では、GunicornがDjangoアプリケーションと対話できることをテストしましたが、アプリケーションサーバーを起動および停止するためのより堅牢な方法を実装する必要があります。 これを実現するために、systemdサービスとソケットファイルを作成します。
Gunicornソケットは起動時に作成され、接続をリッスンします。 接続が発生すると、systemdは接続を処理するためにGunicornプロセスを自動的に開始します。
まず、Gunicornのsystemdソケットファイルを作成して開きます。 sudo
特権:
- sudo nano /etc/systemd/system/gunicorn.socket
内部では、を作成します [Unit]
ソケットを説明するセクション、 [Socket]
ソケットの位置を定義するセクション、および [Install]
ソケットが適切なタイミングで作成されていることを確認するセクション。 次のコードをファイルに追加します。
[Unit]
Description=gunicorn socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
終了したら、ファイルを保存して閉じます。
次に、Gunicornのsystemdサービスファイルを作成して開きます。 sudo
テキストエディタの権限。 サービスファイル名は、拡張子を除いてソケットファイル名と一致する必要があります。
- sudo nano /etc/systemd/system/gunicorn.service
から始めます [Unit]
メタデータと依存関係を指定するセクション。 ここにサービスの説明を入力し、ネットワークターゲットに到達した後にのみこれを開始するようにinitシステムに指示します。 私たちのサービスはソケットファイルのソケットに依存しているため、 Requires
その関係を示すディレクティブ:
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
次に、 [Service]
セクション。 実行する処理を行うユーザーとグループを指定します。 プロセスは関連するすべてのファイルを所有しているため、通常のユーザーアカウントにプロセスの所有権を付与します。 グループの所有権を www-data
NginxがGunicornと簡単に通信できるようにグループ化します。
次に、作業ディレクトリをマップし、サービスの開始に使用するコマンドを指定します。 この場合、仮想環境内にインストールされているGunicorn実行可能ファイルへのフルパスを指定する必要があります。 プロセスを、内で作成したUnixソケットにバインドします。 /run
プロセスがNginxと通信できるようにディレクトリ。 すべてのデータを標準出力に記録して、 journald
プロセスはGunicornのログを収集できます。 ここでは、ワーカープロセスの数など、オプションのGunicornの微調整を指定することもできます。 ここでは、3つのワーカープロセスでGunicornを実行します。
次のサービスセクションをファイルに追加します。 ここにリストされているユーザー名を自分のユーザー名に置き換えてください。
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/django-polls
ExecStart=/home/sammy/envs/polls/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/gunicorn.sock \
mysite.wsgi:application
最後に、 [Install]
セクション。 これにより、起動時にサービスを開始できるようにした場合に、このサービスを何にリンクするかがsystemdに通知されます。 このサービスは、通常のマルチユーザーシステムが稼働しているときに開始する必要があります。
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=sammy
Group=www-data
WorkingDirectory=/home/sammy/django-polls
ExecStart=/home/sammy/envs/polls/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/gunicorn.sock \
mysite.wsgi:application
[Install]
WantedBy=multi-user.target
これで、systemdサービスファイルが完成しました。 今すぐ保存して閉じます。
これで、Gunicornソケットを起動して有効にできます。 これにより、ソケットファイルが次の場所に作成されます。 /run/gunicorn.sock
今そして起動時に。 そのソケットに接続が確立されると、systemdは自動的に gunicorn.service
それを処理するには:
- sudo systemctl start gunicorn.socket
- sudo systemctl enable gunicorn.socket
ソケットファイルを確認することで、操作が成功したことを確認できます。
Gunicornソケットファイルの確認
プロセスのステータスをチェックして、プロセスが正常に開始されたかどうかを確認します。
- sudo systemctl status gunicorn.socket
次の出力が表示されます。
OutputFailed to dump process list, ignoring: No such file or directory
● gunicorn.socket - gunicorn socket
Loaded: loaded (/etc/systemd/system/gunicorn.socket; enabled; vendor preset: enabled)
Active: active (running) since Tue 2019-03-05 19:19:16 UTC; 1h 22min ago
Listen: /run/gunicorn.sock (Stream)
CGroup: /system.slice/gunicorn.socket
Mar 05 19:19:16 django systemd[1]: Listening on gunicorn socket.
次に、の存在を確認します gunicorn.sock
内のファイル /run
ディレクトリ:
- file /run/gunicorn.sock
Output/run/gunicorn.sock: socket
の場合 systemctl status
コマンドはエラーが発生したことを示した、またはあなたが見つからない場合 gunicorn.sock
ディレクトリ内のファイルが表示されている場合は、Gunicornソケットが正しく作成されていないことを示しています。 次のように入力して、Gunicornソケットのログを確認します。
- sudo journalctl -u gunicorn.socket
あなたのをもう一度見てください /etc/systemd/system/gunicorn.socket
続行する前に問題を修正するためのファイル。
ソケットアクティベーションのテスト
現在、始めたばかりの場合 gunicorn.socket
ユニット、 gunicorn.service
ソケットはまだ接続を受信していないため、アクティブにはなりません。 次のように入力して、これを確認できます。
- sudo systemctl status gunicorn
Output● gunicorn.service - gunicorn daemon
Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled)
Active: inactive (dead)
ソケットアクティベーションメカニズムをテストするために、を介してソケットに接続を送信できます curl
次のように入力します。
- curl --unix-socket /run/gunicorn.sock localhost
ターミナルにアプリケーションからのHTML出力が表示されます。 これは、Gunicornが起動し、Djangoアプリケーションを提供できることを示しています。 次のように入力して、Gunicornサービスが実行されていることを確認できます。
- sudo systemctl status gunicorn
Output● gunicorn.service - gunicorn daemon
Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled; vendor preset: enabled)
Active: active (running) since Tue 2019-03-05 20:43:56 UTC; 1s ago
Main PID: 19074 (gunicorn)
Tasks: 4 (limit: 4915)
CGroup: /system.slice/gunicorn.service
├─19074 /home/sammy/envs/polls/bin/python3 /home/sammy/envs/polls/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock mysite.wsgi:application
├─19098 /home/sammy/envs/polls/bin/python3 /home/sammy/envs/polls/bin/gunicorn
. . .
Mar 05 20:43:56 django systemd[1]: Started gunicorn daemon.
Mar 05 20:43:56 django gunicorn[19074]: [2019-03-05 20:43:56 +0000] [19074] [INFO] Starting gunicorn 19.9.0
. . .
Mar 05 20:44:15 django gunicorn[19074]: - - [05/Mar/2019:20:44:15 +0000] "GET / HTTP/1.1" 301 0 "-" "curl/7.58.0"
からの出力の場合 curl
またはの出力 systemctl status
問題が発生したことを示します。詳細については、ログを確認してください。
- sudo journalctl -u gunicorn
あなたもチェックすることができます /etc/systemd/system/gunicorn.service
問題のファイル。 このファイルに変更を加えた場合は、必ずデーモンをリロードしてサービス定義を再読み込みし、Gunicornプロセスを再起動してください。
- sudo systemctl daemon-reload
- sudo systemctl restart gunicorn
Nginxサーバーの構成に進む前に、問題のトラブルシューティングを必ず行ってください。
ステップ8—NginxHTTPSとGunicornプロキシパッシングの設定
Gunicornがより堅牢な方法でセットアップされたので、接続を暗号化し、トラフィックをGunicornプロセスに渡すようにNginxを構成する必要があります。
前提条件に従い、Let’s Encryptを使用してNginxを設定した場合、Nginxで利用可能なドメインに対応するサーバーブロックファイルがすでに用意されているはずです。 sites-available
ディレクトリ。 そうでない場合は、 Ubuntu 18.04でLet’sEncryptを使用してNginxを保護する方法に従って、この手順に戻ります。
これを編集する前に example.com
サーバーブロックファイル、最初に削除します default
Nginxのインストール後にデフォルトでロールアウトされるサーバーブロックファイル:
- sudo rm /etc/nginx/sites-enabled/default
ここで変更します example.com
デフォルトの代わりにトラフィックをGunicornに渡すサーバーブロックファイル index.html
前提条件の手順で構成されたページ。
ドメインに対応するサーバーブロックファイルをエディターで開きます。
- sudo nano /etc/nginx/sites-available/example.com
次のようなものが表示されます。
server {
root /var/www/example.com/html;
index index.html index.htm index.nginx-debian.html;
server_name example.com www.example.com;
location / {
try_files $uri $uri/ =404;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 404; # managed by Certbot
}
これは、 Ubuntu 18.04にNginxをインストールする方法で作成されたデフォルトのサーバーブロックファイルと、Let’sEncryptによって自動的に追加された追加ファイルの組み合わせです。 このファイルの内容を削除し、HTTPトラフィックをHTTPSにリダイレクトし、前の手順で作成したGunicornソケットに着信要求を転送する新しい構成を記述します。
必要に応じて、を使用してこのファイルのバックアップを作成できます cp
. テキストエディタを終了し、という名前のバックアップを作成します example.com.old
:
- sudo cp /etc/nginx/sites-available/example.com /etc/nginx/sites-available/example.com.old
ここで、ファイルを再度開き、その内容を削除します。 新しい構成をブロックごとに作成します。
次のブロックに貼り付けることから始めます。これにより、HTTPリクエストがポートにリダイレクトされます。 80
HTTPSへ:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://example.com$request_uri;
}
ここでは、ポートでHTTPIPv4およびIPv6リクエストをリッスンします 80
リクエストをHTTPSポートにリダイレクトするために301応答ヘッダーを送信します 443
を使用して example.com
ドメイン。 これにより、直接HTTPリクエストがサーバーのIPアドレスにリダイレクトされます。
このブロックの後に、次の設定コードのブロックを追加して、 example.com
ドメイン:
. . .
server {
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;
server_name example.com www.example.com;
# Let's Encrypt parameters
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location = /favicon.ico { access_log off; log_not_found off; }
location / {
proxy_pass http://unix:/run/gunicorn.sock;
proxy_redirect off;
proxy_set_header Host $http_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 https;
}
}
ここでは、最初にポートでリッスンします 443
ヒットするリクエストの場合 example.com
と www.example.com
ドメイン。
次に、デフォルトのサーバーブロックファイルに含まれているものと同じLet’s Encrypt構成を提供します。これは、SSL証明書と秘密鍵の場所、およびいくつかの追加のセキュリティパラメーターを指定します。
The location = /favicon.ico
行は、ファビコンの検索に関する問題を無視するようにNginxに指示します。
最後 location = /
ブロックは、ステップ8で構成されたGunicornソケットにリクエストを渡すようにNginxに指示します。 さらに、リクエストが転送されたことをアップストリームDjangoサーバーに通知し、さまざまなリクエストプロパティを提供するヘッダーを追加します。
これらの2つの構成ブロックを貼り付けると、最終的なファイルは次のようになります。
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://example.com$request_uri;
}
server {
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;
server_name example.com www.example.com;
# Let's Encrypt parameters
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location = /favicon.ico { access_log off; log_not_found off; }
location / {
proxy_pass http://unix:/run/gunicorn.sock;
proxy_redirect off;
proxy_set_header Host $http_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 https;
}
}
終了したら、ファイルを保存して閉じます。
次のように入力して、構文エラーについてNginx構成をテストします。
- sudo nginx -t
構成にエラーがない場合は、次のように入力してNginxを再起動します。
- sudo systemctl restart nginx
これで、サーバーのドメインまたはIPアドレスにアクセスしてアプリケーションを表示できるようになります。 ブラウザは、安全なHTTPS接続を使用してDjangoバックエンドに接続する必要があります。
Djangoプロジェクトを完全に保護するには、いくつかのセキュリティパラメータを追加する必要があります settings.py
ファイル。 エディターでこのファイルを再度開きます。
- nano ~/django-polls/mysite/settings.py
ファイルの一番下までスクロールし、次のパラメータを追加します。
. . .
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_SSL_REDIRECT = True
これらの設定は、サーバーでHTTPSを有効にしていることをDjangoに通知し、「安全な」Cookieを使用するように指示します。 これらの設定の詳細については、DjangoのセキュリティのSSL/HTTPSセクションを参照してください。
完了したら、ファイルを保存して閉じます。
最後に、Gunicornを再起動します。
- sudo systemctl restart gunicorn
この時点で、HTTPリクエストをリダイレクトし、これらのリクエストをGunicornに渡すようにNginxを設定しました。 これで、DjangoプロジェクトとアプリでHTTPSが完全に有効になります。 エラーが発生した場合は、NginxとGunicornのトラブルシューティングに関するこのディスカッションが役立つ場合があります。
警告: CORSヘッダーの構成で説明されているように、Spaces CDNのカスタムサブドメインを構成しなかった場合は、必ずOriginを変更してください。 ]ワイルドカードから *
ドメインからドメイン名(https://example.com
このガイドで)エンドユーザーがアプリにアクセスできるようにする前に。
結論
このガイドでは、Ubuntu18.04サーバーで実行されるスケーラブルなDjangoアプリケーションをセットアップして構成しました。 この設定を複数のサーバーに複製して、高可用性アーキテクチャを作成できます。 さらに、このアプリとその構成は、 Docker または別のコンテナーランタイムを使用してコンテナー化でき、デプロイとスケーリングが容易になります。 これらのコンテナは、Kubernetesなどのコンテナクラスタにデプロイできます。 今後のチュートリアルシリーズでは、このDjangoをコンテナ化して最新化する方法を探ります polls
アプリをKubernetesクラスターで実行できるようにします。
静的ファイルに加えて、DjangoMediaファイルをオブジェクトストレージにオフロードすることもできます。 これを行う方法については、AmazonS3を使用してDjangoサイトの静的ファイルとメディアファイルを保存するを参照してください。 静的ファイルを圧縮して、エンドユーザーへの配信をさらに最適化することも検討してください。 これを行うには、DjangoコンプレッサーのようなDjangoプラグインを使用できます。