Django + Cloud Run + Cloud SQL + Cloud Strageで環境構築

# やりたいこと
・ローカルはdockerで postgre + Django環境
・Deploy環境は Cloud Run + Cloud SQL + Cloud Strage + CI/CD 
でPUSHしたら、環境に反映。

# アカウントとプロジェクトの設定
```
# 目当てのアカウントか確認
gcloud auth list

  Credentialed Accounts
ACTIVE  ACCOUNT
*       hogehoge@gmail.com

To set the active account, run:
    $ gcloud config set account `ACCOUNT`

#　違うので、変更する
gcloud auth login

# 目当てのアカウントか確認
gcloud auth list

         Credentialed Accounts
ACTIVE  ACCOUNT
        hogehoge@gmail.com
*       hugaghuga@gmail.com

To set the active account, run:
    $ gcloud config set account `ACCOUNT`

# 目当てのPJ確認
gcloud config list project

[core]
project = hogehoge-291105

Your active configuration is: [hogehoge-condif]

# 違うので変更する
gcloud config set project hogehoge-233505

# 目当てのPJ確認
gcloud config list project
[core]
project = hogehoge-233505

Your active configuration is: [hogehoge-condif]

```

# APIの有効化
```
gcloud services enable \
  run.googleapis.com \
  sql-component.googleapis.com \
  sqladmin.googleapis.com \
  compute.googleapis.com \
  cloudbuild.googleapis.com \
  secretmanager.googleapis.com


Operation "operations/acf.e5f048a0-3b34-4f0e-9a88-015df1255382" finished successfully.
```

# cloud sqlの設定
```
# ローカル変数を用意
PROJECT_ID=$(gcloud config get-value core/project)
REGION=us-central1

# cloud sqlを作成
gcloud sql instances create hogehoge --project $PROJECT_ID \
  --database-version POSTGRES_11 --tier db-f1-micro --region $REGION
結構時間かかる(10分ぐらい)

Creating Cloud SQL instance...done.                                                                                                                                                                                                                                                                          
Created [https://sqladmin.googleapis.com/sql/v1beta4/projects/999999999/instances/9999999].
NAME       DATABASE_VERSION  LOCATION       TIER         PRIMARY_ADDRESS  PRIVATE_ADDRESS  STATUS
hogehoge  POSTGRES_11       us-central1-a  db-f1-micro  99.999.999.99    -                RUNNABLE

# データベースの作成
gcloud sql databases create tryout --instance hogehoge
Creating Cloud SQL database...done.                                                                                                                                                                                                                                                                          
Created database [tryout].
instance: hogehoge
name: tryout
project: hogehoge-233505

# ユーザの作成
DJPASS="$(cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 30 | head -n 1)"
gcloud sql users create djuser --instance hogehoge --password $DJPASS
Creating Cloud SQL user...done.                                                                                                                                                                                                                                                                              
Created user [djuser].

# envファイルの作成
echo DATABASE_URL=\"postgres://djuser:${DJPASS}@//cloudsql/${PROJECT_ID}:${REGION}:hogehoge/tryout\" > .env
echo GS_BUCKET_NAME=\"${GS_BUCKET_NAME}\" >> .env
echo SECRET_KEY=\"$(cat /dev/urandom | LC_ALL=C tr -dc 'a-zA-Z0-9' | fold -w 50 | head -n 1)\" >> .env
echo DEBUG=\"True\" >> .env

# シークレットの作成
gcloud secrets create application_settings --replication-policy automatic
Created secret [application_settings].

# シークレットにenvファイルを保存
gcloud secrets versions add application_settings --data-file .env
Created version [1] of the secret [application_settings].

```

# Strageの作成
```
# cloud strageの作成
GS_BUCKET_NAME=${PROJECT_ID}-media
gsutil mb -l ${REGION} gs://${GS_BUCKET_NAME}
Creating gs://hogehoge-233505-media/...
```

# Cloud Runにて、Migrateできるように設定
```
# 変数設定
export PROJECTNUM=$(gcloud projects describe ${PROJECT_ID} --format 'value(projectNumber)')
export CLOUDRUN=${PROJECTNUM}-compute@developer.gserviceaccount.com

# Cloud Runからシークレットにアクセスできるように、バインドする
gcloud secrets add-iam-policy-binding application_settings \
  --member serviceAccount:${CLOUDRUN} --role roles/secretmanager.secretAccessor
Updated IAM policy for secret [application_settings].
bindings:
- members:
  - serviceAccount:331170744480-compute@developer.gserviceaccount.com
  role: roles/secretmanager.secretAccessor
etag: BwWwkqh_Jzc=
version: 1

# シークレットの確認
gcloud secrets versions list application_settings
NAME  STATE    CREATED              DESTROYED
1     enabled  2020-10-01T02:17:25  -

# マイグレーション設定
export PROJECTNUM=$(gcloud projects describe ${PROJECT_ID} --format 'value(projectNumber)')
export CLOUDBUILD=${PROJECTNUM}@cloudbuild.gserviceaccount.com

# CloudBuildがシークレット設定にアクセスすることを設定
gcloud secrets add-iam-policy-binding application_settings \
  --member serviceAccount:${CLOUDBUILD} --role roles/secretmanager.secretAccessor
Updated IAM policy for secret [application_settings].
bindings:
- members:
  - serviceAccount:331170744480-compute@developer.gserviceaccount.com
  - serviceAccount:331170744480@cloudbuild.gserviceaccount.com
  role: roles/secretmanager.secretAccessor
etag: BwWwkwj_LAA=
version: 1

# CloudBuildがCloudSQLに接続できるように設定
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
    --member serviceAccount:${CLOUDBUILD} --role roles/cloudsql.client
```

# settings.py
```
# DB設定
DATABASES = {"default": env.db()}
GS_BUCKET_NAME = env("GS_BUCKET_NAME")
STATICFILES_DIRS = []
DEFAULT_FILE_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
STATICFILES_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
```

# cloudmigrate.yaml 
```
cloudmigrate.yaml 
steps:
- name: "gcr.io/cloud-builders/docker"
  args: ["build", "-t", "gcr.io/${PROJECT_ID}/hugahuga-tryout-dev", "."]

- name: "gcr.io/cloud-builders/docker"
  args: ["push", "gcr.io/${PROJECT_ID}/hugahuga-tryout-dev"]

- name: "gcr.io/google-appengine/exec-wrapper"
  args: ["-i", "gcr.io/$PROJECT_ID/hugahuga-tryout-dev",
         "-s", "hugahuga-233505:us-central1:hugahuga",
         "--", "python", "manage.py", "migrate"]

- name: "gcr.io/google-appengine/exec-wrapper"
  args: ["-i", "gcr.io/$PROJECT_ID/hugahuga-tryout-dev",
         "-s", "hugahuga-233505:us-central1:hugahuga",
         "--", "python", "manage.py", "collectstatic", "--no-input"]

- name: "gcr.io/cloud-builders/gcloud"
  id: 'cloudrun-deploy'
  args: ['beta', 'run', 'deploy',
         'hugahuga-tryout-dev',
         '--image', "gcr.io/$PROJECT_ID/hugahuga-tryout-dev",
         '--region', 'asia-northeast1',
         '--platform', 'managed',
         '--add-cloudsql-instances', 'hugahuga-233505:us-central1:hugahuga',
         '--allow-unauthenticated']
```

# イメージをビルドしてMigrateしてデプロイ
```
gcloud builds submit --config cloudmigrate.yaml \
    --substitutions _REGION=asia-northeast1
```

# デプロイコマンド
```
gcloud run deploy django-cloudrun --platform managed --region asia-northeast1\
  --image gcr.io/hogehoge-233505/hogehoge-tryout-dev \
  --add-cloudsql-instances hogehoge-233505:us-central1:hogehoge \
  --allow-unauthenticated
```

# 権限関連
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166346/c0848518-6b2b-e81a-8dea-9bbad55e5443.png)
CI/CDするにはこれだけの権限が必要

# Cloud Build
ここに、トリガーを作成する。
CSRにPUSHされたら、cloudmigrate.yaml を指定してあげればOK！

# 感想
大変でした。WEBにほとんど情報ないので、唯一あった
https://codelabs.developers.google.com/codelabs/cloud-run-django/#0
これを参考にしました。