概要
チュートリアルをやってみたものの、読むべきドキュメントが多くて、行ったり来たりで大変だったので、手順をまとめてみました。
一部どハマりしてスキップした箇所がありますが、デプロイまでできる手順となります。
チュートリアルは下記になります。
App Engine フレキシブル環境での Django の実行
https://cloud.google.com/python/django/flexible-environment?hl=ja
前提
上記記事の「始める前に」を読んで、以下の準備が完了している前提です。
- GCPプロジェクトがある
- プロジェクトの課金が有効
- Google Cloud SDKがインストール済み。
gcloud
コマンドが利用できる - プロジェクトでApp EngineとCloud SQLのAPIが有効になっている
また、Python3系がインストール済みであることも前提です。
環境がない方は以下をご参考ください。
Macでanyenvをつかってpython環境構築(bash、fish対応)
https://cloudpack.media/42033
手順
サンプルアプリのダウンロード
> mkdir 任意のディレクトリ > cd 任意のディレクトリ > git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git > cd python_sample_doc/appengine/flexible/django_cloudsql/
Cloud SQLにインスタンスを作成する
下記を参考にDjangoアプリが利用するデータベースを用意します。
インスタンスを作成する
https://cloud.google.com/sql/docs/postgres/create-instance
Cloud SDK を使用してインスタンスを管理する
https://cloud.google.com/sql/docs/cloud-sdk?hl=ja
先にGCPのプロジェクトを選択しておきます。
> gcloud config list [compute] region = asia-northeast1 zone = asia-northeast1-a [core] account = xxx@xxxxx.xxx disable_usage_reporting = True project = プロジェクトID > gcloud config set project プロジェクトID
とりあえず、お試しなので、最小スペックでインスタンスを作成します。
立ち上がるのに少々お時間がかかります。
> gcloud sql instances create インスタンス名 \ --database-version=POSTGRES_9_6 \ --cpu=1 \ --region=asia-northeast1 \ --memory=3840MiB
インスタンスが作成されたか確認します。
> gcloud sql instances list NAME DATABASE_VERSION LOCATION TIER ADDRESS STATUS インスタンス名 POSTGRES_9_6 asia-northeast1-b db-custom-1-3840 xx.xxx.xxx.xxx RUNNABLE
はい。
インスタンス情報を取得します。
> gcloud sql instances describe インスタンス名 (略) connectionName: プロジェクトID:asia-northeast1:インスタンス名 databaseVersion: POSTGRES_9_6 (略) serviceAccountEmailAddress: xxxx@xxx-xxxx-xx-x.iam.gserviceaccount.com (略)
PostgreSQLユーザーのパスワード設定
下記を参考にしてpostgres
ユーザーにパスワードを設定します。
PostgreSQL ユーザーを作成、管理する
https://cloud.google.com/sql/docs/postgres/create-manage-users?hl=ja
> gcloud sql users set-password postgres no-host \ --instance インスタンス名 \ --password パスワード WARNING: Positional argument deprecated_host is deprecated. Use --host instead. Updating Cloud SQL user...done.
データベースの作成
下記を参考にしてデータベースを作成します。
データベースを作成する
https://cloud.google.com/sql/docs/postgres/create-manage-databases?hl=ja#create
> gcloud sql databases create データベース名 --instance=インスタンス名 Creating Cloud SQL database...done. Created database [データベース名]. instance: インスタンス名 name: データベース名 project: プロジェクトID
データベースが作成されたか確認します。
> gcloud sql databases list --instance=インスタンス名 NAME CHARSET COLLATION postgres UTF8 en_US.UTF8 django-test UTF8 en_US.UTF8
はい。
Djangoアプリの設定
Djangoアプリがデータベースへアクセスできるように設定ファイルを編集します。
vi mysite/settings.py
HOST
には先程gcloud sql instances describe インスタンス名
で取得した、connectionName
を指定します。
gcloud sql instances describe インスタンス名
mysite/settings.py
- 'NAME': 'polls', - 'USER': '<your-database-user>', - 'PASSWORD': '<your-database-password>', + 'NAME': 'データベース名', + 'USER': 'postgres', + 'PASSWORD': 'パスワード', -DATABASES['default']['HOST'] = '/cloudsql/<your-cloudsql-connection-string>' +DATABASES['default']['HOST'] = '/cloudsql/プロジェクトID:asia-northeast1:インスタンス名'
Djangoアプリの準備
Pythonの仮想環境を作成して、必要なパッケージをインストールします。
が、その前にrequirements.txtを編集しておきます。
Postgresqlを利用するチュートリアルなのに、不要でかつ、インストールできないライブラリが指定されていました。
あと、マイグレーションするとライブラリが足りないと怒られるので、先に追加しておきます。
(2018/08/10現在)
> vi requirements.txt
requirements.txt
Django==2.0.3 -mysqlclient==1.3.12 wheel==0.31.0 gunicorn==19.7.1 psycopg2==2.7.4 +psycopg2-binary==2.7.5
> python -m venv venv > . venv/bin/activate # fishはこちら > . venv/bin/activate.fish > pip install -r requirements.txt (略)
Djangoアプリのマイグレーション
アプリの設定とライブラリがインストールできたらマイグレーションを行います。
ローカル環境でCloud SQLへアクセスできるプロキシアプリが提供されているので、新しいターミナルを開いて作業します。
新しいターミナル
> cd 任意のディレクトリ/python_sample_doc/appengine/flexible/django_cloudsql/ > curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64 > chmod +x cloud_sql_proxy > ./cloud_sql_proxy -instances="プロジェクトID:asia-northeast1:インスタンス名"=tcp:5432 2018/08/10 15:55:10 Listening on 127.0.0.1:5432 for プロジェクトID:asia-northeast1:インスタンス名 2018/08/10 15:55:10 Ready for new connections
もとのターミナルに戻ってマイグレーションを実行します。
> python manage.py makemigrations Error during createEphemeral for プロジェクトID:asia-northeast1:インスタンス名: googleapi: Error 403: The client is not authorized to make this request., notAuthorized
はい。
権限がないと怒られました。
調べたところ、Cloud SQLのインスタンスに関連するサービスアカウントに権限付与しないといけなさそう?
先程実行したgcloud sql instances describe インスタンス名
で取得できたserviceAccountEmailAddress
をGCP管理コンソールのIAMに編集者として追加してあげたら良いのかな?
Google Compute Engine(GCE)からCloud SQL接続でハマった
https://qiita.com/NagaokaKenichi/items/b54952e977c13f098bf5
申し訳ありませんが、諸般の都合で、IAM権限が低いため、ここではローカルでの実行をスキップして、Google App Engineへのデプロイへ進みます。
m(_ _)m
ちなみにCloud SQLへアクセスできないので、ローカルでアプリは起動できませんでした。
> python manage.py runserver だめだった。
App Engineへのデプロイ
さて、ローカルでの実行もできたので(大嘘)
いよいよ、App Engineへのデプロイとなります。
まずは、静的コンテンツをCloud Storageへアップします。
バケットを一般読み取り可能にするので、専用のバケットにしたほうが安全です。
# バケットの作成 > gsutil mb gs://静的コンテンツ用のバケット名 Creating gs://静的コンテンツ用のバケット名/... # バケットを一貫読み取り可能にする > gsutil defacl set public-read gs://静的コンテンツ用のバケット名 Setting default object ACL on gs://静的コンテンツ用のバケット名/... # 静的コンテンツを1フォルダにまとめる > python manage.py collectstatic # バケットにコピーする > gsutil rsync -R static/ gs://静的コンテンツ用のバケット名/static
Djangoアプリ設定にアップロードしたフォルダのURLを設定します。
> vi mysite/settings.py
mysite/settings.py
-STATIC_URL = '/static/' +STATIC_URL = 'https://storage.googleapis.com/静的コンテンツ用のバケット名/static/'
App Engineの設定を変更します。
> vi app.yaml
既存のプロジェクトを利用する場合、service
を指定しないと、default
にデプロイされてしまうので、ご注意ください。
app.yaml
# 新しいプロジェクトなら追加は不要 +service: サービス名 - cloud_sql_instances: <your-cloudsql-connection-string> + cloud_sql_instances: プロジェクトID:asia-northeast1:インスタンス名
準備ができたので、デプロイします。
> gcloud app deploy Services to deploy: descriptor: [/任意のディレクトリ/gcp/python-docs-samples/appengine/flexible/django_cloudsql/app.yaml] source: [/任意のディレクトリ/gcp/python-docs-samples/appengine/flexible/django_cloudsql] target project: [プロジェクトID] target service: [サービス名] target version: [バーション] target url: [https://サービス名-dot-プロジェクトID.appspot.com] Do you want to continue (Y/n)? Y (略) DONE (略)
デプロイが完了したら上記のtarget url
にアクセスしてみましょう。
やったぜ。
これでチュートリアルは終了ですが、もうちょっとだけ続くんじゃ。
デプロイ先でマイグレーションする
先程、ローカル環境からCloud SQLにアクセスできないままで、マイグレーションができていないので、ここではデプロイ先のインスタンスに入ってマイグレーションしてみます。
下記を参考にして進めます。
インスタンスをデバッグする
https://cloud.google.com/appengine/docs/flexible/python/debugging-an-instance
gcloud app instances enable-debug
https://cloud.google.com/sdk/gcloud/reference/app/instances/enable-debug
インスタンスのデバッグができるように有効化します。
インスタンスが複数ある場合、どのインスタンスで有効化するか聞かれます。
スケールしているだけなので、どれを選んでも問題ありません。
> gcloud app --project プロジェクトID \ instances enable-debug \ --service=サービス名 \ --version バーション Which instance? [1] サービス名/バージョン/aef-xxxxx-バージョン-bqrz [2] サービス名/バージョン/aef-xxxxx-バージョン-zlqb Please enter your numeric choice: 1 Waiting for operation (略) ...done.
デバッグが有効化されたらインスタンスにログインします。
初回はインスタンスへの接続に利用するrsa keyが生成されます。パスフレーズを忘れないようにしましょう。
> gcloud beta app instances \ --project プロジェクトID \ ssh aef-xxxxx-バーション-zlqb \ --service サービス名 \ --version バーション Generating public/private rsa key pair. Enter passphrase (empty for no passphrase): Enter same passphrase again: (略) Are you sure you want to continue connecting (yes/no)? (略) Enter passphrase for key '/Users/xxx/.ssh/google_compute_engine':
インスタンスにログインできたらさらにDockerコンテナに入ります。
コンテナプロセスを確認するとどうやらgaeapp
がDjangoアプリのコンテナのようです。
インスタンス内
> sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 212d1c1528be us.gcr.io/プロジェクトID/appengine/サービス名.バーション@sha256:xxxx "/bin/sh -c 'exec ..." 18 minutes ago Up 18 minutes 172.17.0.1:8080->8080/tcp gaeapp 269598f6f28c gcr.io/google-appengine/cloud-sql-proxy "/cloud_sql_proxy ..." 19 minutes ago Up 18 minutes cloudsql 9629a8176717 gcr.io/google-appengine/api-proxy "/proxy" 19 minutes ago Up 19 minutes api dae95a724b34 gcr.io/google-appengine/nginx-proxy "/var/lib/nginx/bi..." 19 minutes ago Up 19 minutes 8080/tcp, 8090/tcp, 0.0.0.0:8443->8443/tcp nginx_proxy b3a1a85a156b gcr.io/google-appengine/iap-watcher "./iap_watcher.py ..." 19 minutes ago Up 19 minutes iap_watcher 3d45ca9828db gcr.io/google-appengine/fluentd-logger "/opt/google-fluen..." 20 minutes ago Up 20 minutes fluentd_logger
Dockerコンテナに入ります。
インスタンス内
> docker exec -it gaeapp /bin/bash root@25f63590347e:/home/vmagent/app# ll total 7320 drwxr-xr-x 1 root root 4096 Aug 10 07:37 ./ drwxr-xr-x 1 root root 4096 Jul 9 20:36 ../ -rw-r--r-- 1 root root 988 Aug 9 07:51 README.md -rw-r--r-- 1 root root 271 Aug 10 07:36 app.yaml -rwxr-xr-x 1 root root 7448368 Aug 10 06:39 cloud_sql_proxy* -rwxr-xr-x 1 root root 825 Aug 9 07:51 manage.py* drwxr-xr-x 1 root root 4096 Aug 10 07:41 mysite/ drwxr-xr-x 1 root root 4096 Aug 10 07:41 polls/ -rw-r--r-- 1 root root 83 Aug 10 07:11 requirements.txt -rw-r--r-- 1 root root 136 Jan 1 1970 source-context.json drwxr-xr-x 3 root root 4096 Aug 10 07:37 static
あってました^^
ではコンテナ内でマイグレーションします。
コンテナ内
> python manage.py makemigrations No changes detected > python manage.py makemigrations polls Migrations for 'polls': polls/migrations/0001_initial.py - Create model Choice - Create model Question - Add field question to choice > python manage.py migrate Operations to perform: Apply all migrations: admin, auth, contenttypes, polls, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying polls.0001_initial... OK Applying sessions.0001_initial... OK
やったぜ。
無事に終わったら、コンテナとインスタンスから抜け出しましょう。
> exit > exit
インスタンスでの作業が終わったら、デバッグモードを無効化します。
多分これを忘れると、インスタンスが起動しっぱなしで課金される?(未調査)
> gcloud app --project プロジェクトID \ instances disable-debug \ --service=サービス名 \ --version バーション
どハマりもありましたが、なんとかApp Engine上でDjangoが実行できることが確認できました。
最後に、チュートリアルで作成した、Cloud SQLのインスタンスやApp Engineのサービスは不要であれば削除しておきましょう。
間違って削除してしまわないように、
ほんとうに、
ほんとうに、
ご注意ください。
# App Engineのサービス削除 > gcloud app services delete サービス名 # Cloud SQLインスタンスのデータベース削除 > gcloud sql databases delete データベース名 \ --instance=インスタンス名 # Cloud SQLインスタンス削除 > gcloud sql instances delete インスタンス名 # Cloud Storageのバケット削除 > gsutil rm -r gs://静的コンテンツ用のバケット名
それでは、良きApp Engine上でのDjangoライフを^^
参考
App Engine フレキシブル環境での Django の実行
https://cloud.google.com/python/django/flexible-environment?hl=ja
インスタンスを作成する
https://cloud.google.com/sql/docs/postgres/create-instance
Cloud SDK を使用してインスタンスを管理する
https://cloud.google.com/sql/docs/cloud-sdk?hl=ja
PostgreSQL ユーザーを作成、管理する
https://cloud.google.com/sql/docs/postgres/create-manage-users?hl=ja
データベースを作成する
https://cloud.google.com/sql/docs/postgres/create-manage-databases?hl=ja#create
Google Compute Engine(GCE)からCloud SQL接続でハマった
https://qiita.com/NagaokaKenichi/items/b54952e977c13f098bf5
インスタンスをデバッグする
https://cloud.google.com/appengine/docs/flexible/python/debugging-an-instance
gcloud app instances enable-debug
https://cloud.google.com/sdk/gcloud/reference/app/instances/enable-debug