django-cloud-sql-postgres について
django-cloud-sql-postgres は、Django を Google Cloud SQL for PostgreSQL と App Engine で運用するための設定ガイドです。ローカルと本番の接続、マイグレーション、Gunicorn、一般的な問題の対処方法を開発者向けにまとめています。
主な機能
- 01Django と PostgreSQL の設定
- 02App Engine の Unix ソケット接続
- 03ローカルの Cloud SQL Auth Proxy
- 04データベース移行とデプロイ手順
- 05Gunicorn と静的ファイルの設定
- 06接続に関する一般的な問題の調査
活用シーン
- 01Django アプリを App Engine にデプロイする
- 02プロキシ経由でローカルから Cloud SQL に接続する
- 03本番データベースの認証情報を設定する
- 04接続上限や移行失敗を調査する
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jezweb/ claude-skills --skill django-cloud-sql-postgresインストール後、Claude Code で/django-cloud-sql-postgresを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.md.claude-plugin/plugin.jsonreferences/cloud-sql-proxy-setup.mdiam-authentication.mdmigrations-in-production.mdrules/django-cloud-sql-postgres.mdtemplates/app.yamlrequirements.txtsettings_cloudsql.py詳細
Django on Google Cloud SQL PostgreSQL
ステータス:本番環境対応済み
最終更新日:2026-01-24
依存関係:なし
最新バージョン:[email protected]、[email protected]、[email protected]、[email protected]
クイックスタート(10 分)
1. 依存関係をインストールする
pip install Django psycopg2-binary gunicorn
Cloud SQL Python Connector を使用する場合(ローカル開発に推奨):
pip install "cloud-sql-python-connector[pg8000]"
重要な理由:
psycopg2-binaryは Django 用の PostgreSQL アダプターです- App Engine Standard(Python 3.10 以降)には
gunicornが必要です - Cloud SQL Python Connector を使用すると、SSH トンネルなしで安全に接続できます
2. Django の設定を構成する
settings.py(Unix ソケットを使用する本番環境):
import os
# Detect App Engine environment
IS_APP_ENGINE = os.getenv('GAE_APPLICATION', None)
if IS_APP_ENGINE:
# Production: Connect via Unix socket
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ['DB_NAME'],
'USER': os.environ['DB_USER'],
'PASSWORD': os.environ['DB_PASSWORD'],
'HOST': f"/cloudsql/{os.environ['CLOUD_SQL_CONNECTION_NAME']}",
'PORT': '', # Empty for Unix socket
}
}
else:
# Local development: Connect via Cloud SQL Proxy
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME', 'mydb'),
'USER': os.environ.get('DB_USER', 'postgres'),
'PASSWORD': os.environ.get('DB_PASSWORD', ''),
'HOST': '127.0.0.1',
'PORT': '5432',
}
}
重要:
- App Engine は
/cloudsql/PROJECT:REGION:INSTANCEの Unix ソケット 経由で接続します - ローカル開発では、
127.0.0.1:5432で Cloud SQL Auth Proxy を実行する必要があります - 接続文字列をハードコードせず、環境変数を使用してください
3. app.yaml を作成する
runtime: python310
entrypoint: gunicorn -b :$PORT myproject.wsgi:application
env_variables:
DB_NAME: "mydb"
DB_USER: "postgres"
CLOUD_SQL_CONNECTION_NAME: "project-id:region:instance-name"
# Cloud SQL connection
beta_settings:
cloud_sql_instances: "project-id:region:instance-name"
handlers:
- url: /static
static_dir: static/
- url: /.*
script: auto
secure: always
重要:
beta_settings.cloud_sql_instancesによって/cloudsql/...の Unix ソケットが有効になります- DB_PASSWORD は app.yaml ではなく、
gcloud app deployまたは Secret Manager を使用して設定してください
6 ステップのセットアップ手順
ステップ 1:Cloud SQL インスタンスを作成する
# Create PostgreSQL instance
gcloud sql instances create myinstance \
--database-version=POSTGRES_15 \
--tier=db-f1-micro \
--region=us-central1
# Create database
gcloud sql databases create mydb --instance=myinstance
# Create user
gcloud sql users create postgres \
--instance=myinstance \
--password=YOUR_SECURE_PASSWORD
要点:
- 最高の互換性を得るには、
POSTGRES_15以降を使用してください db-f1-microは開発環境で最も安価です(月額 $7~10)。本番環境ではdb-g1-small以上を使用してください- 接続名を控えておいてください:
PROJECT_ID:REGION:INSTANCE_NAME
ステップ 2:Django プロジェクトを構成する
requirements.txt:
Django>=5.1,<6.0
psycopg2-binary>=2.9.9
gunicorn>=23.0.0
whitenoise>=6.7.0
settings.py への追加項目:
import os
# Security settings for production
DEBUG = os.environ.get('DEBUG', 'False') == 'True'
ALLOWED_HOSTS = [
'.appspot.com',
'.run.app',
'localhost',
'127.0.0.1',
]
# Static files with WhiteNoise
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
MIDDLEWARE.insert(1, 'whitenoise.middleware.WhiteNoiseMiddleware')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
# Database connection pooling
DATABASES['default']['CONN_MAX_AGE'] = 60 # Keep connections open for 60 seconds
これらの設定が必要な理由:
CONN_MAX_AGE=60により接続のオーバーヘッドを削減できます(Cloud SQL には接続数の上限があります)- WhiteNoise を使うと、Cloud Storage なしで静的ファイルを配信できます
- App Engine では
ALLOWED_HOSTSに.appspot.comを含める必要があります
ステップ 3:Cloud SQL Proxy を使用してローカル開発環境をセットアップする
Cloud SQL Auth Proxy をインストールする:
# macOS
brew install cloud-sql-proxy
# Linux
curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.14.1/cloud-sql-proxy.linux.amd64
chmod +x cloud-sql-proxy
プロキシを実行する:
# Authenticate first
gcloud auth application-default login
# Start proxy (runs on 127.0.0.1:5432)
./cloud-sql-proxy PROJECT_ID:REGION:INSTANCE_NAME
# Or with specific port
./cloud-sql-proxy PROJECT_ID:REGION:INSTANCE_NAME --port=5432
ローカル開発用の環境変数を設定する:
export DB_NAME=mydb
export DB_USER=postgres
export DB_PASSWORD=your_password
export DEBUG=True
要点:
- プロキシによって Cloud SQL への安全なトンネルが作成されます
- IP アドレスを許可リストに追加する必要はありません
- パスワード認証と IAM 認証のどちらでも使用できます
ステップ 4:マイグレーションを実行する
# Local (with proxy running)
python manage.py migrate
# Verify connection
python manage.py dbshell
本番環境のマイグレーション(Cloud Build 経由、またはプロキシを使ったローカル環境で実行):
# Option 1: Run locally with proxy
./cloud-sql-proxy PROJECT:REGION:INSTANCE &
python manage.py migrate
# Option 2: Use Cloud Build (recommended)
# See references/cloud-build-migrations.md
ステップ 5:Gunicorn を構成する
gunicorn.conf.py(任意。詳細な調整に使用):
import multiprocessing
# Workers
workers = 2 # App Engine Standard limits this
threads = 4
worker_class = 'gthread'
# Timeout (App Engine has 60s limit for standard, 3600s for flexible)
timeout = 55
# Logging
accesslog = '-'
errorlog = '-'
loglevel = 'info'
# Bind (App Engine sets $PORT)
bind = f"0.0.0.0:{os.environ.get('PORT', '8080')}"
app.yaml の entrypoint オプション:
# Simple (recommended for most cases)
entrypoint: gunicorn -b :$PORT myproject.wsgi:application
# With config file
entrypoint: gunicorn -c gunicorn.conf.py myproject.wsgi:application
# With workers and timeout
entrypoint: gunicorn -b :$PORT -w 2 -t 55 myproject.wsgi:application
要点:
- App Engine Standard ではワーカー数に上限があります(F1:1 ワーカー、F2:2 ワーカー)
- I/O バウンドの Django アプリには
gthreadワーカークラスを使用してください - App Engine にリクエストを終了されないよう、タイムアウトを 60 秒未満に設定してください
ステップ 6:App Engine にデプロイする
# Collect static files
python manage.py collectstatic --noinput
# Deploy
gcloud app deploy app.yaml
# Set DB password via environment
gcloud app deploy --set-env-vars="DB_PASSWORD=your_secure_password"
# View logs
gcloud app logs tail -s default
デプロイを確認する:
# Open in browser
gcloud app browse
# Check database connection
gcloud app logs read --service=default | grep -i database
重要なルール(Django + Cloud SQL)
必ず実施すること:
- App Engine では
/cloudsql/PROJECT:REGION:INSTANCEの Unix ソケット パスを使用する - Unix ソケット接続では
PORT=''(空文字列)を設定する - ローカル開発では Cloud SQL Auth Proxy を使用する
- 接続プーリングのために
CONN_MAX_AGEを設定する(30~60 秒) - データベースの認証情報には 環境変数 を使用する
- 本番環境のパスワードには Secret Manager を使用する
絶対にしないこと:
- データベースのパスワードを
app.yamlに記載する(デプロイ時に Secret Manager または環境変数を使用する) - App Engine で
HOST='localhost'を使用する(Unix ソケットパスを使用する必要があります) - app.yaml の
beta_settings.cloud_sql_instancesを設定し忘れる CONN_MAX_AGE=None(無制限)を設定する(接続プールを使い果たす可能性があります)- Cloud SQL で SSL を無効にする(デフォルトで強制されています)
既知の問題の予防
このスキルでは、文書化されている 12 件の問題を予防します:
Issue #1:OperationalError - No such file or directory
エラー:django.db.utils.OperationalError: could not connect to server: No such file or directory
参照元:https://cloud.google.com/sql/docs/postgres/connect-app-engine-standard
発生する理由:app.yaml に beta_settings.cloud_sql_instances がないため、App Engine が Unix ソケットを見つけられません。
予防策:app.yaml に必ず beta_settings.cloud_sql_instances: "PROJECT:REGION:INSTANCE" を含めてください。
Issue #2:ローカル開発時の接続拒否
エラー:django.db.utils.OperationalError: connection refused または could not connect to server: Connection refused
参照元:https://cloud.google.com/sql/docs/postgres/connect-auth-proxy
発生する理由:Cloud SQL Auth Proxy が起動していないか、誤ったポートにバインドされています。
予防策:Django をローカルで実行する前に cloud-sql-proxy PROJECT:REGION:INSTANCE を起動してください。ポート 5432 で実行されていることを確認してください。
Issue #3:FATAL: password authentication failed
エラー:FATAL: password authentication failed for user "postgres"
参照元:https://cloud.google.com/sql/docs/postgres/create-manage-users
発生する理由:環境変数に設定されたパスワードが間違っているか、Cloud SQL インスタンスにユーザーが存在しません。
予防策:gcloud sql users list --instance=INSTANCE でパスワードを確認してください。必要に応じてリセットします:gcloud sql users set-password postgres --instance=INSTANCE --password=NEW_PASSWORD
Issue #4:接続数の上限超過
エラー:FATAL: too many connections for role "postgres" または remaining connection slots are reserved
参照元:https://cloud.google.com/sql/docs/postgres/quotas#connection_limits
発生する理由:各リクエストでプーリングなしに新しい接続を開くため、25~100 件の接続上限に達します。
予防策:Django の設定で CONN_MAX_AGE = 60 を設定してください。トラフィックが多い場合は、PgBouncer または django-db-connection-pool を使用してください。
Issue #5:App Engine のリクエストタイムアウト
エラー:DeadlineExceededError または 60 秒後にリクエストが終了します。
参照元:https://cloud.google.com/appengine/docs/standard/python3/how-requests-are-handled
発生する理由:データベースクエリまたはマイグレーションに、App Engine の 60 秒の上限を超える時間がかかります。
予防策:Gunicorn のタイムアウトを 55 秒に設定してください。長時間実行されるタスクには、Cloud Tasks または Cloud Run Jobs を使用してください。
Issue #6:本番環境で静的ファイルが 404 になる
エラー:静的ファイルが 404 を返し、CSS/JS が読み込まれません。
参照元:https://cloud.google.com/appengine/docs/standard/serving-static-files
発生する理由:app.yaml に static/ ハンドラーがないか、デプロイ前に collectstatic が実行されていません。
予防策:デプロイ前に python manage.py collectstatic --noinput を実行してください。app.yaml に静的ファイル用のハンドラーを含めてください。
Issue #7:CSRF 検証失敗
エラー:Forbidden (403) CSRF verification failed
参照元:CSRF に関する Django ドキュメント
発生する理由:appspot.com ドメインに対して CSRF_TRUSTED_ORIGINS が設定されていません。
予防策:settings.py に CSRF_TRUSTED_ORIGINS = ['https://*.appspot.com'] を追加してください。
Issue #8:デプロイ後にデータベースが見つからない
エラー:django.db.utils.OperationalError: FATAL: database "mydb" does not exist
参照元:https://cloud.google.com/sql/docs/postgres/create-manage-databases
発生する理由:Cloud SQL にデータベースは存在しますが、DB_NAME 環境変数が間違っています。
予防策:gcloud sql databases list --instance=INSTANCE でデータベース名を確認してください。DB_NAME が完全に一致していることを確認してください。
Issue #9:IAM 認証失敗
エラー:FATAL: Cloud SQL IAM user authentication failed
参照元:https://cloud.google.com/sql/docs/postgres/iam-logins
発生する理由:App Engine のサービスアカウントに roles/cloudsql.instanceUser ロールが付与されていません。
予防策:ロールを付与します:gcloud projects add-iam-policy-binding PROJECT --member="serviceAccount:[email protected]" --role="roles/cloudsql.instanceUser"
Issue #10:本番環境でマイグレーションが失敗する
エラー:マイグレーションがタイムアウトする、またはデプロイ中に実行できない 出典:https://cloud.google.com/sql/docs/postgres/connect-build 原因:App Engine のデプロイにはマイグレーションの手順がなく、エントリーポイントで実行するとタイムアウトします 予防策:Cloud Build を使用してマイグレーションを別途実行するか、デプロイ前に Cloud SQL Proxy を使ってローカルで実行します。
Issue #11:SECRET_KEY の露出
エラー:SECRET_KEY がハードコードされていることに関するセキュリティ警告
出典:Django のデプロイチェックリスト
原因:SECRET_KEY が環境変数や Secret Manager ではなく、settings.py に記述されています
予防策:SECRET_KEY = os.environ.get('SECRET_KEY') を使用し、gcloud app deploy --set-env-vars または Secret Manager で設定します。
Issue #12:コールドスタート時のデータベースタイムアウト
エラー:アイドル期間後の最初のリクエストがタイムアウトする
出典:https://cloud.google.com/appengine/docs/standard/how-instances-are-managed
原因:App Engine インスタンスのコールドスタートに加え、Cloud SQL の有効化に時間がかかります(「オンデマンド」有効化を使用している場合)
予防策:App Engine のウォームアップリクエストを使用するか、Cloud SQL インスタンスを「常時オン」にします(コストが増加します)。app_engine_apis: true を設定し、/_ah/warmup ハンドラーを追加します。
設定ファイルのリファレンス
settings.py(本番環境向けの完全な例)
import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
# Security
SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-key-change-in-production')
DEBUG = os.environ.get('DEBUG', 'False') == 'True'
ALLOWED_HOSTS = [
'.appspot.com',
'.run.app',
'localhost',
'127.0.0.1',
]
# CSRF for App Engine
CSRF_TRUSTED_ORIGINS = [
'https://*.appspot.com',
'https://*.run.app',
]
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Your apps here
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', # Static files
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'myproject.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'myproject.wsgi.application'
# Database
IS_APP_ENGINE = os.getenv('GAE_APPLICATION', None)
if IS_APP_ENGINE:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ['DB_NAME'],
'USER': os.environ['DB_USER'],
'PASSWORD': os.environ['DB_PASSWORD'],
'HOST': f"/cloudsql/{os.environ['CLOUD_SQL_CONNECTION_NAME']}",
'PORT': '',
'CONN_MAX_AGE': 60,
'OPTIONS': {
'connect_timeout': 10,
},
}
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME', 'mydb'),
'USER': os.environ.get('DB_USER', 'postgres'),
'PASSWORD': os.environ.get('DB_PASSWORD', ''),
'HOST': os.environ.get('DB_HOST', '127.0.0.1'),
'PORT': os.environ.get('DB_PORT', '5432'),
'CONN_MAX_AGE': 60,
}
}
# Static files
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'static'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
# Default primary key field type
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# Logging
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
},
},
'root': {
'handlers': ['console'],
'level': 'INFO',
},
'loggers': {
'django': {
'handlers': ['console'],
'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
'propagate': False,
},
},
}
app.yaml(完全な例)
runtime: python310
entrypoint: gunicorn -b :$PORT -w 2 -t 55 --threads 4 myproject.wsgi:application
instance_class: F2
env_variables:
DB_NAME: "mydb"
DB_USER: "postgres"
CLOUD_SQL_CONNECTION_NAME: "project-id:us-central1:instance-name"
DEBUG: "False"
beta_settings:
cloud_sql_instances: "project-id:us-central1:instance-name"
handlers:
- url: /static
static_dir: static/
secure: always
- url: /.*
script: auto
secure: always
automatic_scaling:
min_instances: 0
max_instances: 2
target_cpu_utilization: 0.65
これらの設定の理由:
F2インスタンスクラスでは、Gunicorn ワーカーを 2 つ実行できますmin_instances: 0により、アイドル時のコストを節約できますtarget_cpu_utilization: 0.65により、過負荷になる前にスケーリングします
requirements.txt
Django>=5.1,<6.0
psycopg2-binary>=2.9.9
gunicorn>=23.0.0
whitenoise>=6.7.0
よく使われるパターン
パターン 1:環境に応じたデータベース設定
import os
def get_database_config():
"""Return database config based on environment."""
is_production = os.getenv('GAE_APPLICATION', None)
if is_production:
return {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ['DB_NAME'],
'USER': os.environ['DB_USER'],
'PASSWORD': os.environ['DB_PASSWORD'],
'HOST': f"/cloudsql/{os.environ['CLOUD_SQL_CONNECTION_NAME']}",
'PORT': '',
'CONN_MAX_AGE': 60,
}
else:
return {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME', 'mydb'),
'USER': os.environ.get('DB_USER', 'postgres'),
'PASSWORD': os.environ.get('DB_PASSWORD', ''),
'HOST': '127.0.0.1',
'PORT': '5432',
'CONN_MAX_AGE': 60,
}
DATABASES = {'default': get_database_config()}
使用する場面:ローカル環境と本番環境の整合性が必要な標準的な Django プロジェクト
パターン 2:Secret Manager との統合
from google.cloud import secretmanager
def get_secret(secret_id, version_id='latest'):
"""Retrieve secret from Google Secret Manager."""
client = secretmanager.SecretManagerServiceClient()
project_id = os.environ.get('GOOGLE_CLOUD_PROJECT')
name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}"
response = client.access_secret_version(request={"name": name})
return response.payload.data.decode('UTF-8')
# Usage in settings.py
if os.getenv('GAE_APPLICATION'):
SECRET_KEY = get_secret('django-secret-key')
DB_PASSWORD = get_secret('db-password')
使用する場面:適切なシークレット管理が必要な本番環境へのデプロイ
パターン 3:Cloud SQL Python Connector(Proxy の代替)
# For local development without Cloud SQL Auth Proxy
from google.cloud.sql.connector import Connector
def get_db_connection():
connector = Connector()
return connector.connect(
"project:region:instance",
"pg8000",
user="postgres",
password=os.environ["DB_PASSWORD"],
db="mydb",
)
# In settings.py for local dev (requires pg8000 driver)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydb',
'USER': 'postgres',
'OPTIONS': {
'get_conn': get_db_connection,
},
}
}
使用する場面:Cloud SQL Auth Proxy をインストールできない場合のローカル開発
パターン 4:データベースの検証を含むヘルスチェックエンドポイント
# views.py
from django.http import JsonResponse
from django.db import connection
def health_check(request):
"""Health check endpoint for App Engine."""
try:
with connection.cursor() as cursor:
cursor.execute("SELECT 1")
return JsonResponse({
'status': 'healthy',
'database': 'connected',
})
except Exception as e:
return JsonResponse({
'status': 'unhealthy',
'database': str(e),
}, status=503)
# urls.py
urlpatterns = [
path('_ah/health', health_check, name='health_check'),
]
使用する場面:ロードバランサーのヘルスチェック、データベース接続の監視
同梱リソースの使用
テンプレート(templates/)
templates/settings_snippet.py- データベース設定をコピーして貼り付けられますtemplates/app.yaml- App Engine の完全な設定templates/requirements.txt- 本番環境用の依存関係
リファレンス(references/)
references/cloud-sql-proxy-setup.md- Proxy のインストールと使用方法の詳細references/iam-authentication.md- IAM ベースの認証(パスワード不要)references/secret-manager.md- シークレットを適切に保存する方法references/migrations-in-production.md- マイグレーションを安全に実行する方法
Claude がこれらを読み込むタイミング:
- ローカル接続に問題がある場合は、
cloud-sql-proxy-setup.mdを読み込みます - パスワード不要の認証を設定する場合は、
iam-authentication.mdを読み込みます - 初回の本番環境へのデプロイ前に、
migrations-in-production.mdを読み込みます
高度なトピック
IAM データベース認証
パスワード認証の代わりに、サービス間認証に IAM を使用します。
# Enable IAM authentication on instance
gcloud sql instances patch INSTANCE --database-flags cloudsql.iam_authentication=on
# Create IAM user
gcloud sql users create [email protected] \
--instance=INSTANCE \
--type=CLOUD_IAM_SERVICE_ACCOUNT
# Grant connect permission
gcloud projects add-iam-policy-binding PROJECT \
--member="serviceAccount:[email protected]" \
--role="roles/cloudsql.instanceUser"
IAM 認証用の Django 設定:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ['DB_NAME'],
'USER': f"{os.environ['SERVICE_ACCOUNT']}@{os.environ['PROJECT_ID']}.iam",
'HOST': f"/cloudsql/{os.environ['CLOUD_SQL_CONNECTION_NAME']}",
'PORT': '',
# No PASSWORD needed with IAM auth
}
}
PgBouncer による接続プーリング
トラフィックの多いアプリケーションでは、Cloud Run に PgBouncer をデプロイします。
# Cloud Run service for PgBouncer
# See references/pgbouncer-setup.md for full configuration
PgBouncer を使用する理由:
- Cloud SQL の接続数には上限があります(ティアに応じて 25~4000)
- Django の
CONN_MAX_AGEは役立ちますが、プロセス間で接続をプーリングすることはできません - PgBouncer は真の接続プーリングを提供します
マイグレーションを安全に実行する
方法 1:Cloud Build(推奨)
# cloudbuild.yaml
steps:
- name: 'gcr.io/cloud-builders/gcloud'
args: ['sql', 'connect', 'INSTANCE', '--quiet']
- name: 'python:3.10'
entrypoint: 'bash'
args:
- '-c'
- |
pip install -r requirements.txt
python manage.py migrate --noinput
env:
- 'DB_NAME=mydb'
- 'DB_USER=postgres'
- 'DB_HOST=/cloudsql/PROJECT:REGION:INSTANCE'
secretEnv: ['DB_PASSWORD']
availableSecrets:
secretManager:
- versionName: projects/PROJECT/secrets/db-password/versions/latest
env: 'DB_PASSWORD'
方法 2:Proxy を使ってローカルで実行(簡単)
./cloud-sql-proxy PROJECT:REGION:INSTANCE &
python manage.py migrate
依存関係
必須:
Django>=5.1- Web フレームワークpsycopg2-binary>=2.9.9- PostgreSQL アダプターgunicorn>=23.0.0- App Engine 用 WSGI サーバー
推奨:
whitenoise>=6.7.0- 静的ファイルの配信python-dotenv>=1.0.0- ローカル環境変数
任意:
google-cloud-secret-manager>=2.20.0- Secret Manager との統合cloud-sql-python-connector[pg8000]>=1.12.0- Python ネイティブの Cloud SQL コネクターdjango-db-connection-pool>=1.2.5- コネクションプーリング(CONN_MAX_AGE の代替)
公式ドキュメント
- Cloud SQL for PostgreSQL: https://cloud.google.com/sql/docs/postgres
- App Engine Python 3: https://cloud.google.com/appengine/docs/standard/python3
- Cloud SQL Auth Proxy: https://cloud.google.com/sql/docs/postgres/connect-auth-proxy
- App Engine 上の Django: https://cloud.google.com/python/django/appengine
- Cloud SQL Python Connector: https://github.com/GoogleCloudPlatform/cloud-sql-python-connector
- Secret Manager: https://cloud.google.com/secret-manager/docs
パッケージのバージョン(2026-01-24 確認済み)
{
"dependencies": {
"Django": ">=5.1,<6.0",
"psycopg2-binary": ">=2.9.9",
"gunicorn": ">=23.0.0",
"whitenoise": ">=6.7.0"
},
"optional": {
"google-cloud-secret-manager": ">=2.20.0",
"cloud-sql-python-connector": ">=1.12.0"
}
}
本番環境の例
このスキルは、App Engine での本番 Django デプロイを基にしています:
- ユースケース: マルチテナント SaaS アプリケーション
- トラフィック: 1 日あたり 10K 件以上のリクエスト
- データベース: Cloud SQL PostgreSQL(db-g1-small、25 接続)
- エラー: 0 件(既知の 12 件の問題をすべて防止)
- 検証項目: Unix ソケット接続、コネクションプーリング、静的ファイル、CSRF
トラブルシューティング
問題:ソケットに対して No such file or directory が発生する
解決方法:
- app.yaml の
beta_settings.cloud_sql_instancesを確認します - 接続名の形式を確認します:
PROJECT:REGION:INSTANCE - Cloud SQL インスタンスが存在することを確認します:
gcloud sql instances list
問題:ローカルでは接続できるが、App Engine では失敗する
解決方法:
HOSTが127.0.0.1ではなく、Unix ソケットのパスを使用していることを確認します- app.yaml に環境変数が設定されていることを確認します
- App Engine サービスアカウントに
Cloud SQL Clientロールがあることを確認します
問題:デプロイ中にマイグレーションがタイムアウトする
解決方法:
- app.yaml のエントリーポイントでマイグレーションを実行しないでください
- Cloud Build を使用するか、デプロイ前にプロキシ経由でローカル実行します
- 大規模なマイグレーションの場合は、一時的に Cloud SQL のティアを引き上げます
問題:デプロイ後に静的ファイルが 404 になる
解決方法:
- デプロイ前に
python manage.py collectstatic --noinputを実行します - app.yaml の
static/ハンドラーが正しいディレクトリを指していることを確認します - MIDDLEWARE リストに WhiteNoise が含まれていることを確認します
セットアップ完了チェックリスト
- Cloud SQL PostgreSQL インスタンスを作成済み
- Cloud SQL でデータベースとユーザーを作成済み
- Cloud SQL Auth Proxy をローカルにインストール済み
- Django の設定で Unix ソケット(本番環境)と localhost(開発環境)を指定済み
- app.yaml に
beta_settings.cloud_sql_instancesを設定済み - コネクションプーリング用に
CONN_MAX_AGEを設定済み - 環境変数(DB_NAME、DB_USER など)を設定済み
- DB_PASSWORD を安全に保存済み(app.yaml には記載しない)
- 静的ファイルを収集し、ハンドラーを設定済み
- CSRF_TRUSTED_ORIGINS に *.appspot.com を含める
- 初回デプロイ前にマイグレーションを実行済み(プロキシ経由でローカル実行)
-
gcloud app deployでデプロイ済み - 本番環境のログでデータベース接続を確認済み
ご質問や問題がありますか?
- 上記のトラブルシューティングのセクションを確認してください
- すべての環境変数が正しく設定されていることを確認してください
- 公式ドキュメントを確認してください:https://cloud.google.com/python/django/appengine
- Cloud SQL インスタンスが稼働していることを確認してください:
gcloud sql instances list
最終確認日:2026-01-24 | スキルのバージョン:1.0.0