在Google Cloud Run上部署容器化应用

Google Cloud Run让你无需管理服务器即可运行容器。只需部署Docker镜像,Cloud Run会自动处理扩缩容、HTTPS和基础设施。本教程将带你构建一个Python Flask REST API,将其容器化并部署到Cloud Run。

前置条件

  • 已启用计费的Google Cloud账户
  • 已安装并认证gcloud CLI
  • 本地已安装Docker
  • Python 3.11+
  • 步骤1:创建Flask应用

    创建项目目录并设置应用:

    mkdir cloud-run-demo && cd cloud-run-demo
    

    python -m venv venv && source venv/bin/activate

    pip install flask gunicorn google-cloud-firestore

    创建app.py

    import os
    

    from flask import Flask, jsonify, request

    from google.cloud import firestore

    app = Flask(__name__)

    db = firestore.Client()

    @app.route('/health')

    def health():

    return jsonify({'status': 'healthy', 'service': 'cloud-run-demo'})

    @app.route('/api/items', methods=['GET'])

    def list_items():

    items_ref = db.collection('items')

    docs = items_ref.stream()

    items = [{'id': doc.id, **doc.to_dict()} for doc in docs]

    return jsonify({'items': items, 'count': len(items)})

    @app.route('/api/items', methods=['POST'])

    def create_item():

    data = request.get_json()

    if not data or 'name' not in data:

    return jsonify({'error': 'name is required'}), 400

    item = {

    'name': data['name'],

    'description': data.get('description', ''),

    'created_at': firestore.SERVER_TIMESTAMP

    }

    doc_ref = db.collection('items').add(item)

    return jsonify({'id': doc_ref[1].id, 'message': 'created'}), 201

    @app.route('/api/items/<item_id>', methods=['DELETE'])

    def delete_item(item_id):

    db.collection('items').document(item_id).delete()

    return jsonify({'message': 'deleted'}), 200

    if __name__ == '__main__':

    port = int(os.environ.get('PORT', 8080))

    app.run(host='0.0.0.0', port=port, debug=False)

    创建requirements.txt

    flask==3.0.0
    

    gunicorn==21.2.0

    google-cloud-firestore==2.14.0

    步骤2:编写Dockerfile

    使用多阶段构建创建精简的生产镜像:

    # 构建阶段
    

    FROM python:3.11-slim AS builder

    WORKDIR /app

    COPY requirements.txt .

    RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

    # 生产阶段

    FROM python:3.11-slim

    WORKDIR /app

    COPY --from=builder /install /usr/local

    COPY . .

    ENV PORT=8080

    EXPOSE 8080

    CMD exec gunicorn --bind :$PORT --workers 2 --threads 4 --timeout 120 app:app

    步骤3:本地测试

    docker build -t cloud-run-demo .
    

    docker run -p 8080:8080 -e PORT=8080 cloud-run-demo

    curl http://localhost:8080/health

    步骤4:部署到Google Cloud Run

    export PROJECT_ID=your-project-id
    

    gcloud config set project $PROJECT_ID

    # 启用所需API

    gcloud services enable run.googleapis.com \

    containerregistry.googleapis.com \

    cloudbuild.googleapis.com \

    firestore.googleapis.com

    # 使用Cloud Build构建并推送

    gcloud builds submit --tag gcr.io/$PROJECT_ID/cloud-run-demo

    # 部署到Cloud Run

    gcloud run deploy cloud-run-demo \

    --image gcr.io/$PROJECT_ID/cloud-run-demo \

    --platform managed \

    --region asia-northeast1 \

    --allow-unauthenticated \

    --memory 256Mi \

    --cpu 1 \

    --min-instances 0 \

    --max-instances 10

    步骤5:配置自动扩缩容

    gcloud run services update cloud-run-demo \
    

    --region asia-northeast1 \

    --concurrency 80 \

    --min-instances 1 \

    --max-instances 50

    关键扩缩参数:

  • concurrency:每个实例的最大并发请求数(默认80)
  • min-instances:最小预热实例数(默认0)
  • max-instances:最大实例数(默认100)

步骤6:配置自定义域名

gcloud run domain-mappings create \

--service cloud-run-demo \

--domain api.yourdomain.com \

--region asia-northeast1

步骤7:使用Cloud Build实现CI/CD

创建cloudbuild.yaml

steps:

- name: 'gcr.io/cloud-builders/docker'

args: ['build', '-t', 'gcr.io/$PROJECT_ID/cloud-run-demo:$COMMIT_SHA', '.']

- name: 'gcr.io/cloud-builders/docker'

args: ['push', 'gcr.io/$PROJECT_ID/cloud-run-demo:$COMMIT_SHA']

- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'

entrypoint: gcloud

args: ['run', 'deploy', 'cloud-run-demo', '--image', 'gcr.io/$PROJECT_ID/cloud-run-demo:$COMMIT_SHA', '--region', 'asia-northeast1', '--platform', 'managed']

步骤8:监控和日志

gcloud logging read "resource.type=cloud_run_revision \

AND resource.labels.service_name=cloud-run-demo" \

--limit 50 --format json

添加结构化日志:

import json, sys

def log(severity, message, **kwargs):

entry = {'severity': severity, 'message': message, **kwargs}

print(json.dumps(entry), file=sys.stdout if severity != 'ERROR' else sys.stderr)

成本优化建议

1. 开发环境将min-instances设为0——只在有请求时计费

2. 启用CPU节流减少空闲期成本

3. 内存从256Mi起步,按需增加

4. 使用--cpu-boost加速冷启动

5. 将concurrency设高(80-100)最大化每个实例的请求处理量

总结

Google Cloud Run是介于无服务器函数和完整Kubernetes之间的强大平台。它兼具容器的灵活性和无服务器的简洁性——无需集群管理、自动HTTPS、按使用付费。非常适合API、微服务以及需要高效扩展的Web应用。