哈囉,我們又見面了,昨天 原本要把雲端資料庫也整合好的,可是出了點意外 XD,所以改成今天來完成,我們這次選擇的雲端資料庫是 Google Cloud Platform 的 Cloud SQL 服務。
我想達成的目標是「Commit、Push 到 Github
後,CircleCI
自動執行 CI/CD,部署到 GAE
(Google App Engine)」
前幾天已經走過 CI/CD 且部署到 GAE 了,就差 SQLite
沒有被改為一個真正的雲端資料庫,然而,可是我遇到的問題是:「push 到 Github
後,CircleCI
在跑測試時會報錯,錯誤訊息是: can't connect to local mysql server through socket
,但把測試的 job 拿掉之後,卻又可以正常 deploy 到 GAE
執行」
中間的環節有 Google Cloud SQL
、Google App Engine
、CircleCI 的 build-and-test
job、deploy
job 以及 django
的資料庫設定,總共五個不確定的因素,我就要一個一個去找出來,光是這次要把 SQLite
換成 Google Cloud SQL
就試了 30 次,心累 QQ,希望我浪費掉的這些時間可以幫助到你們。
Cloud SQL
我挑的方案是 MySQL 第二代 5.7 版 standard-1,也就是標準最便宜的方案,但對我來說很夠用了,連接方式很簡單,在 Google Cloud Platform(GCP)
的選單切換到儲存空間分類的 SQL
,然後點 建立執行個體
,選擇適合你的方案,這樣就算建立完成
然後點選左邊選單的 資料庫
→ 建立資料庫,輸入你的資料庫名稱,我這邊的資料庫名字是 shop
,用於在 django 的 settings.py
輸入 NAME
欄位
建立好資料庫之後,切回到選單的 總覽
,找到 執行個體連線名稱
(也就是 Connection Name
),先複製起來,等等貼到 django 的 settings.py
,資料庫的部分到這邊就算搞定,是不是簡單 !? 麻煩的在別的地方 XD
settings.py
這邊是其中一個卡住我的地方,因為我還想要到 CircleCI
做測試,可是我並不知道在封閉的環境之下,到底要怎麼連線到 Cloud SQL
,但經過多番嘗試,最終結果是,在 Django
的測試中,不需要真的連到資料庫,只有在發佈到 App Engine
才連線到真正的資料庫就可以了,真是痛過才知道 QQ
...
if os.getenv('GAE_APPLICATION', None):
DATABASES = {
### mysql of google cloud sql
'default': {
'ENGINE': 'django.db.backends.mysql',
# 這個`shop`,就是在 Cloud SQL 所建立的
# 資料庫名稱(上文有提到該注意的地方)
'NAME': 'shop',
# 在上文提到的 Connection Name
# 的前面加入 /cloudsql/
'HOST': '/cloudsql/django-shop-269303:asia-east1:django-mysql',
# 帳號密碼應該用更安全的方式來放
# 暫時我還不知道怎麼用比較好 QQ
'USER': 'rs',
'PASSWORD': 'admin',
}
}
else:
DATABASES = {
### for testing env
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'shop',
# 除了正式發佈之外的環境
# 就連線到本機端進行測試即可
'HOST': '127.0.0.1',
# 帳號密碼應該用更安全的方式來放
# 暫時我還不知道怎麼用比較好 QQ
'USER': 'rs',
'PASSWORD': 'admin',
}
}
...
Django 需要做的更動就這樣,再來是對我來講很麻煩的 CircleCI
config.yml
設定檔
CircleCI
的 config.yml
設定檔config.yml
放在專案資料夾底下的 .circle
資料夾,這資料夾怎麼來的,可以參考 Day13。
因為我對 CircleCI
的各種設定都還很不熟,所以並不知道詳細執行情況會變什麼樣子,只能透過每次執行出來的錯誤訊息,和透過 ssh 連線進去當下的環境做除錯,就這樣來來回回三十次才成功 QQ,現在就記下來,避免之後再遇到同樣的問題。
config.yml
分成兩個 job,build-and-test
用來做測試,deploy
用來部署到 GAE
。
在 build-and-test
疊了兩層 docker image,是 python
和 mysql
,這個 mysql
的 docker image,就是卡住我的最主要原因,他會自動在本地端執行 mysql server
,所以在測試的階段,就可以連到本地端的 mysql 進行測試。
而我卡住的原因,就是以為在 build-and-test
的階段,就連上真正的 Cloud SQL
,我就在這邊安裝了各種套件: Cloud SDK
、Cloud SQL Proxy
、pymysql
、mysql-client
,然後還把 docker 換成 circleci/cloud-sdk
,各種折騰,才發現根本不需要。只要導入 mysql 的 docker image,然後在 django 連到本地的 mysql
即可。
version: 2.1
orbs:
python: circleci/python@0.2.1
jobs:
build-and-test:
docker:
- image: circleci/python:3.7
- image: circleci/mysql:5.7
environment:
MYSQL_DATABASE: shop
MYSQL_ROOT_HOST: "%"
MYSQL_USER: rs
MYSQL_PASSWORD: admin
executor: python/default
steps:
- checkout
- restore_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements.txt" }}
- run:
command: |
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt
- save_cache:
key: deps1-{{ .Branch }}-{{ checksum "requirements.txt" }}
paths:
- "venv"
- run:
name: Running tests
command: |
. venv/bin/activate
python manage.py test
- store_artifacts:
path: test-reports/
destination: python_app
- persist_to_workspace:
root: .
paths:
- build-and-text
- app.yaml
deploy:
docker:
- image: google/cloud-sdk
steps:
- checkout
- run:
name: Authorizing gcloud
command: |
echo $GCLOUD_SERVICE_KEY | gcloud auth activate-service-account django-shop-269303@appspot.gserviceaccount.com --key-file=-
gcloud --quiet config set project ${GOOGLE_PROJECT_ID}
gcloud --quiet config set compute/zone ${GOOGLE_COMPUTE_ZONE}
- run:
name: Deploy to App Engine
command: |
gcloud app deploy
workflows:
main:
jobs:
- build-and-test
- deploy:
requires:
- build-and-test
就這樣一點東西,搞了我一整天的時間 QQ,看來觀念還是要正確,才不會亂試浪費時間啊 ~ 終於有種撥雲見日的感覺了 !
Photo by Johannes Plenio from Pexels
因為我沒有把整套伺服器加資料庫放到雲端的經驗,也不知道通常是怎麼串起來的,再加上我還要透過 CircleCI
來做 CI/CD,整套流程要串起來真的是有點不知所措,都不知道到底是哪個環節出了問題,只能一個一個去試,真的很浪費時間,可是我身邊的朋友都沒有用過 CircleCI
,也沒有用 Django
串 CircleCI
最後架在 GAE
上的經驗,只好自己踩踩雷了。
經過這次的體驗,又更懂架站的坑流程了呢~
我是 RS,這是我的 不做怎麼知道系列 文章,我們 明天見。
HELLO!您好!看了您的django部署在app engine的教學,受益良多!
想再請教,如何在app engine上面執行makemigrations呢?
是否能透過google SDK或shell執行?
Hi taco,
不需要在 app engine 上面執行 makemigrations
哦,當你更動了你的資料庫表的欄位才需要執行 makemigrations
,通常都是在本地端執行即可。
想知道關於詳細 makemigrations
這個指令做了什麼事,可以參考官方解釋。
喔喔!了解了,感謝釋疑:)