はじめに
Google CloudのCloud Runでは、開発したアプリケーションをgcloudコマンドで簡単にデプロイすることができます。
今回はDockerfileを作成せず、ソースコードから直接デプロイする際に環境変数を設定しながらデプロイする方法を紹介します。アプリケーションはPythonのフレームワーク(Django,Flask,FastAPI)で試してみたいと思います。
前提
Google Cloud,gcloud CLIの準備として以下の「始める前に」を実行済みとします。
Pythonのバージョンは全て3.11.9で試しています。
また、環境変数を設定してデプロイする際、.envファイルから環境変数を取得してデプロイに使用する前提としています。その際に使用できるシェルスクリプトを作成しました。gcloud run deployコマンドを使用しています。
全環境共通で、以下のファイル(deploy.sh)を使用します。今回はPythonで試していますが、それ以外でも以下のファイルは使い回せると思います。
#!/bin/bash
# アプリケーション名とリージョン、その他パラメータを設定
APP_NAME="sample-app-name" # 任意のアプリケーション名を設定してください
REGION="asia-northeast1" # 今回は東京リージョンに設定します
MEMORY="512Mi"
CPU="1"
MIN_INSTANCES="0"
MAX_INSTANCES="1"
# 環境変数をCloud Run用のフォーマットに変換する関数
format_env_vars() {
local result=""
while IFS='=' read -r key value; do
# コメントや空行をスキップ
[[ $key =~ ^#.*$ ]] && continue
[[ -z $key ]] && continue
# 値をそのまま使用
result+="$key=$value,"
done < .env
echo "${result%,}" # 最後のカンマを削除
}
# 環境変数を整形
ENV_VARS=$(format_env_vars)
# デプロイコマンドを構築
DEPLOY_CMD="gcloud run deploy $APP_NAME \
--source . \
--region $REGION \
--set-env-vars $ENV_VARS \
--memory $MEMORY \
--cpu $CPU \
--min-instances $MIN_INSTANCES \
--max-instances $MAX_INSTANCES \
--allow-unauthenticated" # 今回は認証なしでアクセスできる前提とします
# コマンドを表示(デバッグ用)
echo "実行するコマンド:"
echo "$DEPLOY_CMD"
# デプロイを実行
eval "$DEPLOY_CMD"
echo "デプロイが完了しました。"
Djangoのサンプル
ライブラリ・ディレクトリ構成
まずはDjangoから紹介します。ライブラリは以下を使用します。
Django==5.1.1
gunicorn==23.0.0
ディレクトリ構成は以下の通りです。
.
├── Procfile
├── deploy.sh # デプロイ時に使用するシェルスクリプトです
├── manage.py # デフォルトのまま
├── requirements.txt
├── sample_app
│ ├── admin.py # デフォルトのまま
│ ├── apps.py # デフォルトのまま
│ ├── migrations # デフォルトのまま
│ ├── models.py # デフォルトのまま
│ ├── templates
│ │ └── index.html
│ ├── tests.py # デフォルトのまま
│ └── views.py
└── sample_django_cloud_run
├── asgi.py # デフォルトのまま
├── settings.py
├── urls.py
└── wsgi.py # デフォルトのまま
サンプルコード
今回は環境変数が読み込めるかの確認のため、html上で表示してみます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>django-sample</title>
</head>
<body>
<h1>Hello Django</h1>
<p>TEST_VARIABLE1 の値: {{ test_var1 }}</p>
<p>TEST_VARIABLE2 の値: {{ test_var2 }}</p>
</body>
</html>
import os
from django.shortcuts import render
# Create your views here.
def index(request):
test_var1 = os.environ.get('TEST_VARIABLE1', 'Not set')
test_var2 = os.environ.get('TEST_VARIABLE2', 'Not set')
context = {
'test_var1': test_var1,
'test_var2': test_var2,
}
return render(request, 'index.html', context)
実装自体はこれで終わりです。Djangoで必要なアプリ設定・ルーティング設定だけしておきます。
from django.contrib import admin
from django.urls import path
from sample_app.views import index
urlpatterns = [
path('admin/', admin.site.urls),
path('', index, name='index'), # 追加
]
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'sample_app', # 追加
]
また、Djangoにおいては本番環境の運用において、settings.pyでALLOWED_HOSTSを適切に設定しなければなりません。
今回は環境変数でホストを設定しておくこととします。
import os
ALLOWED_HOSTS = []
if os.environ.get("CLOUD_RUN_URL"):
ALLOWED_HOSTS.append(os.environ["CLOUD_RUN_URL"])
Cloud Runのデフォルトドメインを使用する場合、以下のようなURLとなります。
https://< APP_NAME >-< Google Cloud プロジェクト番号 >.<リージョン名>.run.app
では、実際にデプロイしてみます。.envファイルには以下のような記載をしておきます。
TEST_VARIABLE1=Hello-Django
TEST_VARIABLE2=Cloud-Run
CLOUD_RUN_URL=<ホストを設定>
Procfileを作成し、以下のように記述しておきます。
web: gunicorn sample_django_cloud_run.wsgi --bind :$PORT --workers 1 --threads 8 --timeout 0
こちらにてPythonではProcfileが必須とのことなので、Djangoに限らず作成しています。
以下のコマンドを実行し、デプロイを実施します。処理は数分〜10分程度かかるかと思います。
※deploy.shのAPP_NAME等、設定は必要に応じて修正してください。
bash deploy.sh # zshでもOK
正常に完了するとデプロイ先のURLがターミナル上に表示されているかと思いますので、アクセスしてみます。
ちゃんと環境変数も合わせてデプロイできているようです!
Flaskのサンプル
ライブラリ・ディレクトリ構成
続いてFlaskです。ライブラリは以下を使用します。
Flask==3.0.3
gunicorn==20.1.0
ディレクトリ構成は以下の通りです。
.
├── Procfile
├── deploy.sh
├── main.py
├── requirements.txt
└── templates
└── index.html
サンプルコード
Djangoと同様、環境変数を読み込んでhtml上で表示してみます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>flask-sample</title>
</head>
<body>
<h1>Hello Flask</h1>
<p>TEST_VARIABLE1 の値: {{ test_var1 }}</p>
<p>TEST_VARIABLE2 の値: {{ test_var2 }}</p>
</body>
</html>
from flask import Flask, render_template
import os
app = Flask(__name__)
@app.get("/")
def index():
# 環境変数から値を取得
test_var1 = os.getenv('TEST_VARIABLE1', 'Not set')
test_var2 = os.getenv('TEST_VARIABLE2', 'Not set')
return render_template('index.html', test_var1=test_var1, test_var2=test_var2)
if __name__ == "__main__":
app.run(host="localhost", port=8080, debug=True)
では、デプロイを行なってみます。Django同様、.envとProcfileを作成します。
TEST_VARIABLE1=Hello-Flask
TEST_VARIABLE2=Cloud-Run
web: gunicorn main:app --bind :$PORT --workers 1 --threads 8 --timeout 0
以下のコマンドを実行します。
※deploy.shのAPP_NAME等、設定は必要に応じて修正してください。
bash deploy.sh # zshでもOK
Flaskも環境変数と合わせてデプロイできました!
FastAPIのサンプル
ライブラリ・ディレクトリ構成
続いてはFastAPIで試してみます。ライブラリは以下を使用します。Django,Flaskとは異なり、FastAPIで推奨されているuvicornを使用します。
fastapi==0.115.0
uvicorn==0.30.6
ディレクトリ構成は以下の通りです。FastAPIはAPI開発に特化したフレームワークですので、これまでとは異なりHTMLに表示はしません。
.
├── Procfile
├── deploy.sh
├── main.py
└── requirements.txt
サンプルコード
FastAPIでは、環境変数を読み込んでそれを返すAPIで試してみます。
from fastapi import FastAPI
import os
app = FastAPI()
@app.get("/")
async def index():
# 環境変数から値を取得
test_var1 = os.getenv('TEST_VARIABLE1', 'Not set')
test_var2 = os.getenv('TEST_VARIABLE2', 'Not set')
return {'test_var1': test_var1, 'test_var2': test_var2}
これまでと同じ流れでデプロイを行います。.envとProcfileを作成します。
TEST_VARIABLE1=Hello-FastAPI
TEST_VARIABLE2=Cloud-Run
web: uvicorn main:app --host 0.0.0.0 --port $PORT
以下のコマンドを実行します。
※deploy.shのAPP_NAME等、設定は必要に応じて修正してください。
bash deploy.sh # zshでもOK
こちらもうまくデプロイできました!
まとめ
今回はCloud RunにPythonで開発したアプリケーションを簡単にデプロイする手順をまとめてみました。環境変数をいくつか設定したいことはよくあると思いますので、そのような時に参考としてもらえると幸いです。
Cloud Runはコンテナ実行のプラットフォームですが、Dockerfileを作成しなくてもソースコードだけで簡単にデプロイできるのは嬉しいですね。実際にはCI/CDで運用することが多いと思いますので、その辺りも試してみたいです。