google-app-engine

安装量: 253
排名: #3454

安装

npx skills add https://github.com/jezweb/claude-skills --skill google-app-engine

Google App Engine

Status: Production Ready Last Updated: 2026-01-24 Dependencies: Google Cloud SDK (gcloud CLI) Skill Version: 1.0.0

Quick Start (10 Minutes) 1. Prerequisites

Install Google Cloud SDK

macOS

brew install google-cloud-sdk

Or download from https://cloud.google.com/sdk/docs/install

Authenticate

gcloud auth login gcloud config set project YOUR_PROJECT_ID

Enable required APIs

gcloud services enable appengine.googleapis.com gcloud services enable sqladmin.googleapis.com gcloud services enable secretmanager.googleapis.com

  1. Create app.yaml

app.yaml - Standard Environment (Python 3.12)

runtime: python312 instance_class: F2

env_variables: DJANGO_SETTINGS_MODULE: "myproject.settings.production"

handlers: # Static files (served directly by App Engine) - url: /static static_dir: staticfiles/ secure: always

# All other requests go to the app - url: /.* script: auto secure: always

automatic_scaling: min_instances: 0 max_instances: 10 target_cpu_utilization: 0.65

  1. Deploy

Deploy to App Engine

gcloud app deploy

Deploy with specific version

gcloud app deploy --version=v1 --no-promote

View logs

gcloud app logs tail -s default

Standard vs Flexible Environment Standard Environment (Recommended for Most Apps)

Use when: Building typical web apps, APIs, or services that fit within runtime constraints.

Aspect Standard Startup Fast (milliseconds) Scaling Scale to zero Pricing Pay per request Runtimes Python 3.8-3.12 Instance Classes F1, F2, F4, F4_1G Max Request 60 seconds Background Cloud Tasks only

app.yaml - Standard

runtime: python312 instance_class: F2

Flexible Environment

Use when: Need custom runtimes, Docker, longer request timeouts, or background threads.

Aspect Flexible Startup Slower (minutes) Scaling Min 1 instance Pricing Per-hour VM Runtimes Any (Docker) Max Request 60 minutes Background Native threads

app.yaml - Flexible

runtime: python env: flex

runtime_config: runtime_version: "3.12"

resources: cpu: 1 memory_gb: 0.5 disk_size_gb: 10

automatic_scaling: min_num_instances: 1 max_num_instances: 5

Cost Warning: Flexible always runs at least 1 instance (~$30-40/month minimum).

Cloud SQL Connection Standard Environment (Unix Socket)

App Engine Standard connects to Cloud SQL via Unix sockets, not TCP/IP.

settings.py

import os

if os.getenv('GAE_APPLICATION'): # Production: Cloud SQL 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: Cloud SQL Proxy or local DB DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.environ.get('DB_NAME', 'localdb'), 'USER': os.environ.get('DB_USER', 'postgres'), 'PASSWORD': os.environ.get('DB_PASSWORD', ''), 'HOST': '127.0.0.1', 'PORT': '5432', } }

app.yaml

env_variables: DB_NAME: "mydb" DB_USER: "myuser" CLOUD_SQL_CONNECTION_NAME: "project:region:instance"

CRITICAL: Beta settings for Cloud SQL socket

beta_settings: cloud_sql_instances: "project:region:instance"

CRITICAL: The beta_settings.cloud_sql_instances enables the Unix socket. Without it, connection fails.

Local Development with Cloud SQL Proxy

Download and run Cloud SQL Proxy

cloud-sql-proxy PROJECT:REGION:INSTANCE --port=5432

Or use Docker

docker run -p 5432:5432 \ gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.8.0 \ PROJECT:REGION:INSTANCE

Static Files with Cloud Storage Option 1: App Engine Static Handlers (Simple)

app.yaml

handlers: - url: /static static_dir: staticfiles/ secure: always expiration: "1d"

Collect static files before deploy

python manage.py collectstatic --noinput gcloud app deploy

Limitation: Files bundled with deploy, limited to 32MB per file.

Option 2: Cloud Storage (Recommended for Production)

settings.py

from google.cloud import storage

GS_BUCKET_NAME = os.environ.get('GS_BUCKET_NAME') STATICFILES_STORAGE = 'storages.backends.gcloud.GoogleCloudStorage' DEFAULT_FILE_STORAGE = 'storages.backends.gcloud.GoogleCloudStorage'

Or with django-storages

STORAGES = { "default": { "BACKEND": "storages.backends.gcloud.GoogleCloudStorage", "OPTIONS": { "bucket_name": GS_BUCKET_NAME, "location": "media", }, }, "staticfiles": { "BACKEND": "storages.backends.gcloud.GoogleCloudStorage", "OPTIONS": { "bucket_name": GS_BUCKET_NAME, "location": "static", }, }, }

Install django-storages

pip install django-storages[google]

Create bucket with public access for static files

gsutil mb -l us-central1 gs://YOUR_BUCKET_NAME gsutil iam ch allUsers:objectViewer gs://YOUR_BUCKET_NAME

Environment Variables and Secrets Simple: app.yaml env_variables

app.yaml - NOT for secrets!

env_variables: DJANGO_SETTINGS_MODULE: "myproject.settings.production" DEBUG: "False"

Warning: app.yaml is committed to source control. Never put secrets here.

Production: Secret Manager

settings.py

from google.cloud import secretmanager

def get_secret(secret_id, version="latest"): """Fetch 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}" response = client.access_secret_version(request={"name": name}) return response.payload.data.decode("UTF-8")

Usage

if os.getenv('GAE_APPLICATION'): SECRET_KEY = get_secret('django-secret-key') DB_PASSWORD = get_secret('db-password')

Create secrets

echo -n "your-secret-key" | gcloud secrets create django-secret-key --data-file=- echo -n "db-password" | gcloud secrets create db-password --data-file=-

Grant App Engine access

gcloud secrets add-iam-policy-binding django-secret-key \ --member="serviceAccount:YOUR_PROJECT@appspot.gserviceaccount.com" \ --role="roles/secretmanager.secretAccessor"

Scaling Configuration Automatic Scaling (Default) automatic_scaling: min_instances: 0 # Scale to zero when idle max_instances: 10 # Cap maximum instances target_cpu_utilization: 0.65 target_throughput_utilization: 0.6 max_concurrent_requests: 80 min_pending_latency: 30ms max_pending_latency: automatic

Basic Scaling (Background Tasks) basic_scaling: max_instances: 5 idle_timeout: 5m

Use for: Services that need to run background work without scaling to zero immediately.

Manual Scaling (Fixed Instances) manual_scaling: instances: 3

Use for: Predictable workloads, WebSocket connections, or when you need guaranteed capacity.

Instance Classes Class Memory CPU Cost/hour F1 256 MB 600 MHz $0.05 F2 512 MB 1.2 GHz $0.10 F4 1 GB 2.4 GHz $0.20 F4_1G 2 GB 2.4 GHz $0.30

Recommended for Django

instance_class: F2 # 512MB usually sufficient

Upgrade to F4 if you see memory errors or slow response times.

Known Issues Prevention

This skill prevents 6 documented issues:

Issue #1: Cloud SQL Connection Refused

Error: could not connect to server: Connection refused Why It Happens: Missing beta_settings.cloud_sql_instances in app.yaml Prevention: Always include:

beta_settings: cloud_sql_instances: "project:region:instance"

Issue #2: Static Files 404

Error: Static files return 404 after deploy Why It Happens: collectstatic not run, or handler order wrong Prevention:

python manage.py collectstatic --noinput

And ensure static handler comes before catch-all:

handlers: - url: /static static_dir: staticfiles/ - url: /.* script: auto

Issue #3: 502 Bad Gateway

Error: 502 errors on first request or under load Why It Happens: Cold start timeout, app takes too long to initialize Prevention:

Optimize app startup (lazy imports, connection pooling) Use min_instances: 1 to avoid cold starts Increase instance_class for more CPU/memory Issue #4: Memory Limit Exceeded

Error: Exceeded soft memory limit in logs Why It Happens: F1 class (256MB) too small for Django + dependencies Prevention: Use instance_class: F2 minimum for Django apps

Issue #5: Request Timeout

Error: DeadlineExceededError after 60 seconds Why It Happens: Standard environment has 60s request limit Prevention:

Move long tasks to Cloud Tasks Use Flexible environment for longer timeouts Optimize database queries Issue #6: Secret Key in Source Control

Error: Django SECRET_KEY exposed in git history Why It Happens: Putting secrets in app.yaml env_variables Prevention: Use Secret Manager (see Environment Variables section)

Deployment Commands

Deploy default service

gcloud app deploy

Deploy specific service

gcloud app deploy app.yaml --service=api

Deploy without promoting (for testing)

gcloud app deploy --version=v2 --no-promote

Split traffic between versions

gcloud app services set-traffic default --splits=v1=0.5,v2=0.5

Promote version

gcloud app versions migrate v2

View logs

gcloud app logs tail -s default

Open app in browser

gcloud app browse

List versions

gcloud app versions list

Delete old versions

gcloud app versions delete v1 v2 --quiet

Multi-Service Architecture myproject/ ├── app.yaml # Default service ├── api/ │ └── app.yaml # API service ├── worker/ │ └── app.yaml # Background worker └── dispatch.yaml # URL routing

dispatch.yaml

dispatch: - url: "/api/" service: api - url: "/tasks/" service: worker

Deploy all services

gcloud app deploy app.yaml api/app.yaml worker/app.yaml dispatch.yaml

Common Patterns Health Check Endpoint

urls.py

urlpatterns = [ path('_ah/health', lambda r: HttpResponse('ok')), # ... other urls ]

app.yaml

liveness_check: path: "/_ah/health" check_interval_sec: 30 timeout_sec: 4 failure_threshold: 2 success_threshold: 2

readiness_check: path: "/_ah/health" check_interval_sec: 5 timeout_sec: 4 failure_threshold: 2 success_threshold: 2

Warmup Requests

app.yaml

inbound_services: - warmup

urls.py

urlpatterns = [ path('_ah/warmup', warmup_view), ]

views.py

def warmup_view(request): """Pre-warm caches and connections.""" from django.db import connection connection.ensure_connection() return HttpResponse('ok')

HTTPS Redirect

app.yaml

handlers: - url: /.* script: auto secure: always # Redirects HTTP to HTTPS

Local Development Using Cloud SQL Proxy

Terminal 1: Run Cloud SQL Proxy

cloud-sql-proxy PROJECT:REGION:INSTANCE --port=5432

Terminal 2: Run Django

export DB_HOST=127.0.0.1 export DB_PORT=5432 python manage.py runserver

Using dev_appserver (Legacy)

Not recommended - use Django's runserver instead

dev_appserver.py app.yaml

Environment Detection

settings.py

import os

Detect App Engine environment

IS_GAE = os.getenv('GAE_APPLICATION') is not None IS_GAE_LOCAL = os.getenv('GAE_ENV') == 'localdev'

if IS_GAE: DEBUG = False ALLOWED_HOSTS = ['.appspot.com', '.your-domain.com'] else: DEBUG = True ALLOWED_HOSTS = ['localhost', '127.0.0.1']

Bundled Resources Templates (templates/) app.yaml - Standard environment configuration app-flex.yaml - Flexible environment configuration requirements.txt - Common dependencies for App Engine References (references/) instance-classes.md - Detailed instance class comparison common-errors.md - Error messages and solutions Official Documentation App Engine Python: https://cloud.google.com/appengine/docs/standard/python3 app.yaml Reference: https://cloud.google.com/appengine/docs/standard/reference/app-yaml Cloud SQL: https://cloud.google.com/sql/docs/postgres/connect-app-engine-standard Secret Manager: https://cloud.google.com/secret-manager/docs Scaling: https://cloud.google.com/appengine/docs/standard/how-instances-are-managed Dependencies

requirements.txt

gunicorn>=21.0.0 google-cloud-secret-manager>=2.16.0 google-cloud-storage>=2.10.0 django-storages[google]>=1.14.0 psycopg2-binary>=2.9.9 # For PostgreSQL

Production Checklist SECRET_KEY in Secret Manager (not app.yaml) DEBUG = False in production settings ALLOWED_HOSTS configured for your domain collectstatic runs before deploy beta_settings.cloud_sql_instances set Instance class appropriate (F2+ for Django) HTTPS enforced (secure: always) Health check endpoint configured Error monitoring set up (Cloud Error Reporting)

Last verified: 2026-01-24 | Skill version: 1.0.0

返回排行榜