【初心者向け】DjnagoアプリをGAE(GCP)でデプロイする方法
本日はGCP(Google Cloud Platform)を使ってDjnagoアプリをデプロイする方法について解説していきます。
GCPとは、Google がクラウド上で提供するサービス群の総称であり、AWS同様に簡単にWebサービスのインフラ環境を構築することができます。
GCPの特徴としてはGoogleが提供していることもあり、機械学習におけるサービスに強みがあると言われていますが、GCP自体登場し始めたのがここ数年のため、有益な情報が少ないのが現状です。
本記事を通じてGCPを使っていただくきっかけになればと思います。
1. 本記事の解説内容
以下の内容を主に解説していきます。
・GAEへのデプロイ
・Cloud SQL(MySQL)との連携
2. GAEとは
GAE(Google App Engine)とはGCP(Google Cloud Platform)のサービスの一つであり、Webアプリを簡単にデプロイ・運用するためのサービスです。
もう少し専門的な話をすると、PaaS(Platform as a Service)といわれる、アプリケーションソフトが稼動するためのハードウェアやOSなどのプラットフォーム一式を、インターネット上のサービスとして提供するものです。
特徴としては、デプロイの構成もサーバー管理も不要なため、アプリ開発に集中できます。またトラフィックが急激に跳ね上がった場合もアプリケーションが自動的にスケールされるため、いちいち管理して設定変更して...とする必要がありません。
またsnapchatのような大規模サービスの実績もあることから、信頼性は高いかと思います。
GAEについての概要はこの辺にして、以降では実際に使用方法について解説していきます。
3. GAEへのデプロイ方法
ハンズオン形式で解説していきます。
3.1 事前準備
デプロイするDjangoアプリをローカル環境に準備します。
以下のアプリを用いて解説していきます。(もちろん他のアプリを使っていただいてもOKです。)
https://github.com/shogo6768/snsproject
上記のリンクからリポジトリのURLをコピーします。(方法は下図)
ターミナル上で以下のコマンドを実行し、ローカル環境にファイルをコピーします。先ほどコピーしたurlを<レポジトリurl>の部分にペーストしてください。
$ git clone <レポジトリurl>
またこれから色々なライブラリをインストールしておくので、以下のコマンドで仮想環境を作っておきましょう。
$ python -m venv venv #末尾にvenvは任意名
以下のコマンドで仮想環境に入ります。
$ source venv/bin/activate #仮想環境に入るとターミナル上に(venv)と表示される。
次に必要ライブラリをインストールしていきます。
(venv)$ pip install django
(venv)$ pip install django-allauth
2行目のdjango-allauthについては、今回使用するベースアプリの認証機能で使われているためインストールします。django-allauthを使用していないアプリを使う場合は割愛してください。
なお以降ではpython3前提で解説しますのでpython2を使用される方は切り替えておくことをオススメします。
python2 → python3への切り替え方法↓
3.2 GCPへの登録
GCPへの登録がお済みの方は飛ばしてください。
これから登録される方は、まずGoogleアカウントを準備しログインしてください。
次にGCPとgoogle chrome上で「GCP」と検索し、一番上に出てくる「Google Cloud...」をクリックします。トップページ上の「無料で使ってみる」ボタンをクリックし、以下の情報を入力していけば登録完了です。
・国と通貨
・口座の種類(ビジネス/個人)
・名前と住所
・お支払い方法(クレジットカード/デビットカード)
・使用言語
これから実装する内容は、90 日間有効の $300 分のクレジットで対応可能なので費用が発生することはないと思います。
3.3 GAEのデプロイ
以下のフローで解説していきます。
・GCPプロジェクトの作成
・GAE開始
・googleSDKインストール
なおここからの作業には費用が発生しますのでご注意ください。
GCP登録したばかりの人は無料クレジット内で対応可能です。
◆GCPプロジェクトの作成
ここからは図を用いながら解説していきますが、GCPのUIは頻繁に変わるので、多少見え方が異なる場合がありますのであらかじめご了承ください。
(多少UI変わっても設定する上でそんなに支障はないかと思います。)
まずはプロジェクトの作成をしていきます。
登録後が完了していれば以下の画面を確認できますので、赤枠の「プロジェクト選択」をクリックします。
プロジェクト選択をクリックすると以下の画面が表示されますので、赤枠の「新しいプロジェクト」をクリックします。
新しいプロジェクトをクリックすると以下の画面が表示されますので、任意の「プロジェクト名」を入力して「作成」をクリックします。なお、本記事ではsnsappというプロジェクト名で進めていきます。
プロジェクト作成は以上になります。
作成が完了すると以下のようにプロジェクト情報等が記載された画面が表示されます。
◆GAE開始
以下の通り「App Engine」をクリックします。
すると以下の画面が表示されるので「アプリケーションを作成」をクリックします。
クリックすると以下の通りリージョンを選択できるので「aisia-notheast1」を選択し「次へ」をクリックします。ちなみにaisia-notheast1は東京リージョンのことです。
なお今回は、言語はもちろん「python」で環境は「標準」で進めていきます。
ちなみに環境は「標準」と「フレキシブル」の二種類あり、フレキシブルはその名の通りカスタマイズ性が高くDockerを扱うことができます。ただし標準と比べて料金が高くなりやすいので注意が必要です。
以上でGAEの設定は完了です。
◆googleSDKインストールと初期設定
GAEへデプロイするには、gcloudというコマンドラインを使ってデプロイしていきます。
gcloudコマンドラインを使うためにgoogleSDKをインストールしていきます。
以下のリンクよりまずは必要パッケージをダウンロードします。
自身のPCのOSに合うパッケージをダウンロードします。
ダウンロードしたファイルを展開するとgoogle-cloud-sdkというフォルダが作成されるので、ホームディレクトリに移動しましょう。(GoogleがHomeディレクトリに配置することを推奨しています。)
ホームディレクトリにフォルダを配置できたら、以下のコマンドでインストールを実行します。
(venv)$ cd #すでにホームディレクトリの場合不要
(venv)$ ./google-cloud-sdk/install.sh #インストール
インストールを進めていくといくつか質問が来るので以下のように入力すればOKです。
Do you want to help improve the Google Cloud SDK (y/N)? y #ここはNでもOK
...
Modify profile to update your $PATH and enable shell command
completion?
Do you want to continue (Y/n)? Y #パスの作成なのでYを入力
・・・
Enter a path to an rc file to update, or leave blank to use
[/Users/shogosaito/.zshrc]: #後者のpathで問題なしのためエンターを入力
作成したGCPプロジェクトを先ほどインストールしたCloud SDKから操作するにはgoogleアカウントの認証と初期設定を行う必要がありますので、以下の初期化コマンドを入力します。
(venv)$ ./google-cloud-sdk/bin/gcloud init
初期化コマンドを入力すると以下のように表示されます。configration(設定名)を選択する必要がありますがこちらは[default]の"1"を選択すれば基本OKです。ただしプロジェクトが多数存在する場合は、"2"を選択し管理しやすくしてもいいかと思います。
Pick configuration to use:
[1] Re-initialize this configuration [default] with new settings
[2] Create a new configuration
Please enter your numeric choice: 1
configrationを選択すると以下の画面が表示されますので"1"を選択すればOKです。初めて認証する方はgoogleの認証画面が自動で表示されるかもしれませんが認証するgoogleアカウントを選択してもらえればOKです。
Choose the account you would like to use to perform operations for
this configuration:
[1] xxxxxxxxx@gmail.com
[2] Log in with a new account
Please enter your numeric choice: 1
アカウントを選択すると以下の画面が表示されますので該当するプロジェクトを選択します。
Pick cloud project to use:
...
[7] ...
[8] snsapp-316122
[9] ...
...
Please enter numeric choice or text value (must exactly match list
item): 8
上記プロジェクトの選択では以下のIDの部分が表示されますので、確認しながら該当するものを選択してください。
以上でgoogleSDKの設定は完了です。
◆app.yamlファイルの作成
GAEでデプロイするには、以下のようにapp.yamlファイルをBASE_DIR直下に配置する必要があります。
snsproject
├── config
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── snsapp
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── static
├── templates
├── app.yaml #GAE設定用ファイル追加
└── manage.py
app.yamlファイル内に設定を記述していきます。
#インストールされているバージョンによって末尾の数字調整
runtime: python39
# 下記は 設定用ディレクトリ.wsgi:application のように記述
entrypoint: gunicorn -b :$PORT config.wsgi:application
# 下記はhttpでアクセスがあった際、httpsにリダイレクトするための記述
handlers:
- url: .*
secure: always
script: auto
”runtime”には使用する言語環境を記載します。
”entrypoint”には本番環境時の起動の起点となる場所を記述し、djangoではwsgi.py内のapplicationを起点とするため上記のように記述します。configの部分は各人の設定ディレクトリによって記述が変わるためご注意ください。(設定用ディレクトリ.wsgi:application )
”handlers”の部分にはurlに関する記述を設定します。今回はhttpでアクセスした場合httpsにリダイレクトするための記述をしています。
その他色々設定することは可能ですが、全てを紹介するのは難しいので必要な設定については以下をご参照ください。
◆必要ライブラリのインストールとその他ファイル設定
先ほどapp.yaml内のentrypointでgunicornの記述をしましたが、ginicornをインストールする必要があります。
(venv)$ pip install gunicorn
gunicornのインストールが完了したら、requrements.txtを作成します。作成理由は、GAEのサーバーにどのようなライブラリをインストールするか知らせるためです。BASE_DIR直下で以下のコマンドを実行し、requrements.txtを作成します。requirements.txtにはインストールしているライブラリとバージョンが記述されます。
(venv)$ pip freeze > requirements.txt
なお以降では、新たにライブラリをインストールするたびに上記のコマンドを実行し、requirements.txtをアップデートしていきます。
◆本番環境と開発環境で設定内容分岐
本番環境と開発環境ではDEBUGの設定等異なる部分があるので、分岐した内容をsettings.pyに記述していきます。
settings.py
import os
if os.getenv('GAE_APPLICATION', None):
# 本番環境
DEBUG = False
ALLOWED_HOSTS = ['<本番環境ドメイン>']
else:
# 開発環境
DEBUG = True
ALLOWED_HOSTS = ['*']
上記の分岐は、本番環境と開発環境の分岐で、GAE経由でアプリを動かす本番環境下ではif直下が適用され、python manage.py runserver経由でアプリを動かす開発環境下ではelse直下が適用されます。
ちなみにALLOWED_HOSTSの本番環境ドメインは以下のデプロイコマンドを実行した時に表示される情報より取得します。
#gcloud app deploy --project=<gcpのプロジェクトID>でデプロイ
(venv)$ gcloud app deploy --project=snsapp-316122
Services to deploy:
descriptor: [/Users/shogosaito/Desktop/snsproject/snsproject/app.yaml]
....
target url: [https://snsapp-316122.an.r.appspot.com]
target service account: [App Engine default service account]
gcloud app deploy...を入力するとtarget urlと表示されるのでsettings.pyのALLOWED_HOSTSにhttps://以降のドメイン部(snsapp-316122.an.r.appspot.com)を貼り付けましょう。
settings.pyにドメイン部を追記できたら、再度デプロイコマンドを入力して実行してください。
#gcloud app deploy --project=<gcpのプロジェクトID>でデプロイ
(venv)$ gcloud app deploy --project=snsapp-316122
・・・
Do you want to continue (Y/n)? Y
デプロイコマンドを実行すると、GCSにファイルがアップロードされる処理が行われるので、完了次第以下のコマンドでデプロイした内容をブラウザ上で確認できます。
(venv)$ gcloud app browse
上記のような画面が表示さればデプロイ完了です。ただしこのままでは新規登録もログインできずエラーとなります。理由はデータベースの設定がされていないためです。データベースの設定については以降で解説していきます。
4. Cloud SQL(MySQL)との連携
Cloud SQLでは自動バックアップ、ストレージの自動増量、メンテナンス等DBを運用する上で面倒な部分をGCP側が対応してくれます。
ただ料金も結構高いので使用済みのものはクリーンアップ(削除)するようにしていきましょう。
4.1 Cloud SQL連携のための事前準備
Cloud SQLと連携するためにCloud SQL Auth Proxyを使う必要があります。では設定方法について解説していきます。
◆Cloud SQL Admin APIの有効化
まずは上記リンク内の以下の部分をクリックしてCloud SQL Admin API を有効にします。
ボタンをクリックすると以下のページに飛ぶので、使用しているgcpプロジェクトを選択します。
続行をクリックすると以下の画面になります。
認証情報に進むと以下の画面が表示されるのでCloud SQL Admin APIが選択されていることを確認してください。
スクロールダウンすると以下の画面が表示されるので、以下赤枠の二つを選択して次へをクリックします。
次へをクリックすると、以下の画面が表示されるので完了をクリックするとAPIの有効化は完了です。
◆gcloudにログインする
Cloud SQL Admin API を使用するために、新しい認証情報を取得します。以下のコマンドを実行してください。
(venv)$ gcloud auth application-default login
◆Cloud SQL Proxy のインストール
続いてCloud SQL Auth Proxyをダウンロードしてインストールしていきます。各OSに合わせて以下のコマンドをターミナル上に入力します。
macOS64ビットの場合
(venv)$ curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64
(venv)$ chmod +x cloud_sql_proxy
Windows64ビットの場合
https://dl.google.com/cloudsql/cloud_sql_proxy_x64.exe
を右クリックして [名前を付けてリンク先を保存] を選択し、Cloud SQL Auth Proxy をダウンロードします。ファイル名を cloud_sql_proxy.exe に変更します。
4.2 DBインスタンスの作成
以下のようにGCPコンソール画面よりSQLを選択します。
SQLを選択したらインスタンスの作成をクリックします。
今回はデータベースエンジンとしてMySQLを選択します。
次にCompute Engine APIを有効化をしていない方は、有効化の画面が表示されますので有効化してください。
以下の画面でインスタンスの設定をしていきます。インスタンスIDは任意名を入力してください。パスワードについては控をとっておいてください。
スクロールダウンして以下のようにリージョンとゾーンを以下のように設定します。本番環境では、複数のゾーン(高可用性)の方が障害に強いためベターですが、コストが高くなるので今回はシングルゾーンとします。
さらにスクロールダウンしていくとインスタンスをカスタマイズできます。
マシンタイプでメモリを選択できるので、一番コストの低い共有コア 1 vCPU 0.614GBとします。
ストレージはSSD(推奨)の10GBを選択し、ストレージの自動増量を有効にします。ストレージ容量は後から減らすことはできないため小さめで設定して自動増量するのがいいかと思います。
接続方法はCloud SQLプロキシを使用するのでパブリックIPにチェック入れます。
以下はバックアップの設定です。自動バックアップの時間帯はなるべくサービス利用者の少ない時間帯に設定するのが無難かと思います。ポイントインタイムもデフォルト設定でOKと思います。
メンテナンスはバグの修正、セキュリティ侵害の防止、アップグレードの実施のために行われます。その際インスタンスを再起動する必要があるので、利用ユーザーの少ない時間帯に設定するのがいいと思います。
その他は基本デフォルトの設定のままでいいかと思うのでインスタンスを作成します。
4.3 ユーザーとデータベースの作成
インスタンスの作成が完了したら、ユーザーとデータベースを設定していきます。
設定は簡単でGCPコンソール上で設定していきます。
まずはユーザーの設定です。
SQLの画面上で、上記①、②の順にクリックするとサイドバーが表示されユーザー名とパスワードを入力できます。入力が完了したら追加ボタンをクリックしユーザを追加しましょう。なおここで入力したユーザー名とパスワードは後に使用するので控えて置きましょう。
次にデータベースの設定をしていきます。
ユーザー設定同様に、①、②の順でクリックするとサイドバーが表示されるので、データベース名を入力しデータベースを作成します。なおここで作成するデータベース名も後に使用するので控えて置きましょう。
4.4 settings.pyにDB情報の記述
Cloud SQLで設定した情報をdjangoのsettings.pyに記載します。
config/settings.py
import os
if os.getenv('GAE_APPLICATION', None):
# GAE本番環境
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '/cloudsql/[YOUR_INSTANCE_CONNECTION_NAME]',
'USER': '[YOUR-USERNAME]',
'PASSWORD': '[YOUR-PASSWORD]',
'NAME': '[YOUR-DATABASE]',
}
}
else:
# 開発環境
# 事前に./cloud_sql_proxyを実行してプロキシ経由でアクセスできるようにする必要がある。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1',
'PORT': '3306',
'USER': '[YOUR-USERNAME]',
'PASSWORD': '[YOUR-PASSWORD]',
'NAME': '[YOUR-DATABASE]',
}
}
DEBUGの記述同様、本番環境と開発環境を分けて記述します。
[YOUR-USERNAME]、[YOUR-PASSWORD]、[YOUR-DATABASE]は先ほどCloud SQLで設定したものを記載します。HOST'内にある[YOUR_INSTANCE_CONNECTION_NAME]については、Cloud SQL概要の以下を記載します。
settings.pyの記述は以上です。ただし、settings.pyにDBのユーザー名やパスワードなどの記述はセキュリティの観点から好ましくないです。このような環境変数の取り扱いについては「6. 環境変数の取り扱い」にて解説します。
4.5 本番環境での確認
本番環境でcloud sqlを使うためにまず開発環境でDBテーブルを作成する必要があります。
テーブル作成にあたってはいつもどおり、makemigrations、migrateとしていきますが、今回MySQLを使用するにあたって、mysqlclientをインストールする必要があります。以下のコマンドを順に実行しましょう。
(venv)$ brew install mysql
(venv)$ pip install mysqlclient
mysqlclientのインストールが完了したら、以下のコマンドでrequirements.txtにインストールしたmysqlclient情報を追記しましょう。
(venv)$ pip freeze > requirements.txt
また開発環境でcloud sqlで設定したDB情報を使うにはCloud SQL Proxyを起動させる必要があります。
もう一つ別のターミナルを開き以下を実行します。[YOUR_INSTANCE_CONNECTION_NAME] の部分には先ほど同様に接続名を入力します。
(venv)$ ./cloud_sql_proxy -instances="[YOUR_INSTANCE_CONNECTION_NAME]"=tcp:3306
起動すると接続状態になるので、この状態で以下のコマンドを実行し、テーブル作成します。
(venv)$ python manage.py makemigrations
(venv)$ python manage.py migrate
以上でテーブル作成完了です。
また、後に使うので管理者権限をもったユーザーを作成して置きましょう。
(venv)$ python manage.py createsuperuser
試しに開発環境で確認してみましょう。
(venv)$ python manage.py runserver
先ほど作成した管理者権限を持ったユーザーでログインしてみます。
ログイン完了し、以下の画面が表示されれば無事データベースとの連携完了です。
本番環境でも同様に確認してみましょう。
#gcloud app deploy --project=<gcpのプロジェクトID>でデプロイ
(venv)$ gcloud app deploy --project=snsapp-316122
#ブラウザで確認
(venv)$ gcloud app browse
以下のように画面が表示され、先ほど作成した管理者権限ユーザーでのログインもできます。
ログイン後以下が表示
5. 管理画面のcss反映
現段階では管理画面を見てみると以下のようにcssがあたっていません。
ここからはcssを適用していきます。
本番環境ではcollectstaticというコマンドを使って、static関連のファイルを一箇所に集約して、djangoに読み込ませます。
collectstaticを使うにはいくつか設定が必要なので解説していきます。
config/settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR / 'static']
STATIC_ROOT = BASE_DIR / 'staticfiles' #追加
STATIC_ROOTを設定します。今回はBASE_DIR直下のstaticfilesに集約させます。したがってBASE_DIR直下にstaticfilesというディレクトリを作成します。
次にurlを設定します。
config/urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static #追加
urlpatterns = [
...
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)+ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
# +static...を追加
以上で設定完了です。
以下のコマンドを実行します。(-noinputでY/Nの確認省略)
(venv)$ python manage.py collectstatic —-noinput
#実行すると以下のような文言が表示されます。
... static files copied...
またGAEでは静的ファイルが格納された場所を明示する必要があるのでapp.yaml内に以下の記述をします。
app.yaml
runtime: python39
...
handlers:
#以下追加
- url: /static
static_dir: staticfiles/
以上で設定は完了です。
もう一度デプロイして確認してみましょう。
#gcloud app deploy --project=<gcpのプロジェクトID>でデプロイ
(venv)$ gcloud app deploy --project=snsapp-316122
#ブラウザで確認
(venv)$ gcloud app browse
管理画面を確認すると以下の通りcssがあたっているのがわかるかと思います。
6. 環境変数の取り扱い
Cloud SQLとの連携で説明した通り、settings.pyにDB情報を記載するのはセキュリティの観点から好ましくありません。
以降では環境変数をどのように扱うかについて解説していきます。
今回はdjnagoで簡単に環境変数を管理できる、django-environというライブラリを使っていきます。早速インストールしていきましょう。
(venv)$ pip install django-environ
インストールが終わったら、requirements.txtに追記しましょう。
(venv)$ pip freeze > requirements.txt
環境変数を処理していきます。考え方はシンプルで、.envというバージョン管理しないファイルの中に環境変数を記述し、settings.pyでは.envファイルより変数を読み込みます。
記述方法について解説していきます。
from pathlib import Path
import os
import environ #インポート
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
#.envファイルの場所指定
env = environ.Env()
env.read_env(os.path.join(BASE_DIR, '.env'))
SECRET_KEY = env('SECRET_KEY') #シークレットキーは.envに記述
...
#DBのセキュリティに関わる部分は.env何に記述
if os.getenv('GAE_APPLICATION', None):
# GAE本番環境
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '/cloudsql/{}'.format(env('DB_HOST')),
'USER': env('DB_USER'),
'PASSWORD': env('DB_PASSWORD'),
'NAME': env('DB_NAME'),
}
}
else:
# 開発環境
# 事前に./cloud_sql_proxyを実行してプロキシ経由でアクセスできるようにする必要がある。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1',
'PORT': '3306',
'USER': env('DB_USER'),
'PASSWORD': env('DB_PASSWORD'),
'NAME': env('DB_NAME'),
}
}
今回はシークレットキーとDBに関わる情報を.envに記述します。
(今回の設定ではないですが、emailアドレス等あればそちらも.envに記述ください。)
まず.envファイルが存在する場所を決めます。コードにもある通り、.envファイルの場所をBASE_DIRとします。
env('SECRET_KEY')、env('DB_HOST')の部分が.envファイルより読み込む部分となります。
したがってBASE_DIRに.envファイルを作成し、以下のように記述してください。
.envファイル
SECRET_KEY=[YOUR-SECRET-KEY]
DB_HOST=[YOUR-INSTANCE-CONNECTION-NAME]
DB_USER=[YOUR-USERNAME]
DB_PASSWORD=[YOUR-PASSWORD]
DB_NAME=[YOUR-DATABASE]
また.envをバージョン管理しないように.gitignore内にも.envを追記しましょう。
あとは、gcloud deploy...といつも通りデプロイすれば完了です。
7. 最後に
GAEについて解説しましたがいかがだったでしょう。
GAEは仮想サーバーを作成して設定する方法よりも設定が少なく、かなり簡単にデプロイできると思いますので是非試してみてください。
1点注意事項があります。
GAEの継続不要の場合は、必ずクリーンアップ(削除)するようにしてください。特にCloud SQLを放っておくとなかなかの額請求されるので不要なら必ずクリーンアップしてください。
では本日は以上です。
この記事が気に入ったらサポートをしてみませんか?