Esta página foi traduzida pela API Cloud Translation.
Switch to English

Como executar o Django no Cloud Run (totalmente gerenciado)

A implantação de aplicativos com estado, como o Django, integra vários serviços para que interajam juntos e formem um projeto coeso.

Neste tutorial, presume-se que você esteja familiarizado com o desenvolvimento de Web com Django. O código de exemplo implementa visualizações de base, modelos e configurações de rota. Combinada com o administrador interativo do Django, esta amostra de código mostra como integrar bancos de dados gerenciados, armazenamento de objetos, secrets criptografados e criar pipelines com computação sem servidor.

Embora este tutorial demonstre especificamente o Django, é possível usar esse processo de implantação com outros frameworks baseados em Django, como Wagtail e Django CMS.

Diagrama mostrando a arquitetura da implantação.
O site Django é veiculado a partir do Cloud Run, que usa vários serviços de apoio para armazenar diferentes tipos de dados (informações de banco de dados relacional, recursos de mídia, secrets de configuração e imagens de contêiner). Os serviços de back-end são atualizados pelo Cloud Build como parte de uma tarefa de criação e migração.

Custos

Antes de começar

  1. Faça login na sua conta do Google.

    Se você ainda não tiver uma, inscreva-se.

  2. No Console do Google Cloud, na página do seletor de projetos, selecione ou crie um projeto do Google Cloud.

    Acessar a página do seletor de projetos

  3. Verifique se o faturamento está ativado para seu projeto na nuvem. Saiba como confirmar se o faturamento está ativado para o projeto.

  4. Ative as APIs Cloud Run, Cloud SQL, Cloud Build, Secret Manager, and Compute Engine .

    Ative as APIs

  5. Instale e inicialize o SDK do Cloud..
  6. Verifique se as permissões suficientes estão disponíveis para a conta usada neste tutorial.

Como clonar o app Django

Depois de concluir os pré-requisitos, faça o download e implante o app de amostra do Django. As seções a seguir contêm as etapas de configuração, execução e implantação do aplicativo.

Como clonar o app do Django

O código para o aplicativo de amostra Django está no repositório GoogleCloudPlatform/python-docs-samples no GitHub.

  1. É possível fazer o download da amostra como um arquivo ZIP e extraí-lo ou clonar o repositório na máquina local:

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git

  2. Acesse o diretório que contém o código de amostra:

Linux/MacOS

  cd python-docs-samples/run/django

Windows

  cd python-docs-samples\run\django

Como preparar os serviços de apoio

Neste tutorial, usamos vários serviços do Google Cloud para fornecer o banco de dados, o armazenamento de mídia e o armazenamento de secrets compatíveis com o projeto Django implantado. Esses serviços são implantados em uma região específica. Para a eficácia entre serviços, é melhor que todos os serviços sejam implantados na mesma região. Para mais informações sobre a região mais próxima de você, consulte Produtos disponíveis por região.

Configurar uma instância do Cloud SQL para PostgreSQL

O Django é compatível com vários bancos de dados relacionais, mas oferece o maior suporte do PostgreSQL, que é um dos tipos de banco de dados oferecidos no Cloud SQL.

As seções a seguir descrevem a criação de uma instância, um banco de dados e um usuário do banco de dados do PostgreSQL para o aplicativo de pesquisas.

Criar uma instância do PostgreSQL

Console

  1. No Console do Cloud, acesse a página Instâncias do Cloud SQL.

    Acessar a página "Instâncias" do Cloud SQL

  2. Clique em Create Instance.

  3. Clique em PostgreSQL.

  4. No campo ID da instância, digite um nome para a instância (INSTANCE_NAME).

  5. Insira uma senha para o usuário postgres.

  6. Use os valores padrão dos outros campos.

  7. Clique em Criar.

gcloud

  1. Crie a instância do PostgreSQL:

    gcloud sql instances create INSTANCE_NAME \
        --project PROJECT_ID \
        --database-version POSTGRES_12 \
        --tier db-f1-micro \
        --region REGION
    

    Substitua:

    • INSTANCE_NAME: o nome da instância do Cloud SQL.
    • PROJECT_ID: o ID do projeto do Google Cloud
    • REGION: a região do Google Cloud

    Leva alguns minutos para criar a instância e ela deve estar pronta para uso.

  2. Defina a senha do usuário postgres.

    gcloud sql users set-password postgres \
        --instance INSTANCE_NAME --prompt-for-password
    

Crie um banco de dados

Console

  1. No Console do Cloud, acesse a página Instâncias do Cloud SQL.

    Acessar a página "Instâncias" do Cloud SQL

  2. Selecione a instância INSTANCE_NAME.

  3. Acesse a guia Bancos de dados.

  4. Clique em Create database.

  5. Na caixa de diálogo Nome do banco de dados, insira DATABASE_NAME.

  6. Clique em Criar.

gcloud

  • Crie o banco de dados na instância recém-criada:

    gcloud sql databases create DATABASE_NAME \
        --instance INSTANCE_NAME
    

    Substitua DATABASE_NAME por um nome para o banco de dados dentro da instância.

Criar um usuário

Console

  1. No Console do Cloud, ative o Cloud Shell.

    Ativar o Cloud Shell

  2. No Cloud Shell, use o cliente gcloud integrado para se conectar à instância INSTANCE_NAME:

    gcloud sql connect INSTANCE_NAME --user postgres
    
  3. Insira a senha do usuário do postgres.

    Agora você está usando o psql. Você verá o prompt postgres=>.

  4. Crie um usuário:

    CREATE USER django WITH PASSWORD 'PASSWORD';
    

    Substitua PASSWORD por uma senha secreta suficiente.

  5. Conceda direitos totais sobre o novo banco de dados para o novo usuário:

    GRANT ALL PRIVILEGES ON DATABASE DATABASE_NAME TO django;
    
  6. Saia de psql:

    \q
    

gcloud

  1. Inicie uma conexão com a instância do SQL:

    gcloud sql connect INSTANCE_NAME --user postgres
    

    Substitua INSTANCE_NAME pela instância criada do Cloud SQL.

  2. Insira a senha do usuário do postgres.

    Agora você está usando o psql. Você verá o prompt postgres=>.

  3. Crie um usuário:

    CREATE USER django WITH PASSWORD 'PASSWORD';
    
  4. Conceda direitos totais sobre o novo banco de dados para o novo usuário:

    GRANT ALL PRIVILEGES ON DATABASE DATABASE_NAME TO django;
    
  5. Saia de psql:

    \q
    

Configurar um bucket do Cloud Storage

É possível armazenar recursos estáticos incluídos no Django e mídia enviada por usuários em armazenamento de objetos altamente disponível usando o Cloud Storage. O pacote django-storages[google] processa a interação do Django com esse back-end de armazenamento.

Console

  1. No Console do Cloud, acesse a página Navegador do Cloud Storage.

    Acessar a página "Navegador do Cloud Storage"

  2. Clique em Criar bucket.
  3. Na caixa de diálogo Criar bucket, especifique os seguintes atributos.
  4. Clique em Criar.

gcloud

A ferramenta de linha de comando gsutil foi instalada como parte da instalação do SDK do Cloud.

  • Crie um bucket do Cloud Storage:

    gsutil mb -l REGION gs://PROJECT_ID_MEDIA_BUCKET
    

    Substitua MEDIA_BUCKET por um sufixo para o bucket de mídia. Combinado com o ID do projeto, isso cria um nome de bucket exclusivo.

Armazenar valores do secret no Secret Manager

Agora que os serviços de backup estão configurados, o Django precisa de informações sobre esses serviços. Em vez de colocar esses valores diretamente no código-fonte do Django, este tutorial usa o Secret Manager para armazenar essas informações com segurança.

O Cloud Run e o Cloud Build interagem com os secrets usando as respectivas contas de serviço, identificadas por um endereço de e-mail que contém o número do projeto.

Criar o arquivo de ambiente Django como um secret do Secret Manager

Você armazena as configurações necessárias para iniciar o Django em um arquivo .env protegido. O código de amostra usa a API Secret Manager para recuperar o valor do secret e o pacote django-environ para carregar os valores no ambiente Django. A chave secreta está configurada para ser acessível pelo Cloud Build e pelo Cloud Run, porque ambos os serviços executarão o Django.

  1. Crie um arquivo chamado .env, definindo a string de conexão do banco de dados, o nome do bucket de mídia e um novo valor SECRET_KEY:

    DATABASE_URL=postgres://django:PASSWORD@//cloudsql/PROJECT_ID:REGION:INSTANCE_NAME/DATABASE_NAME
    GS_BUCKET_NAME=PROJECT_ID_MEDIA_BUCKET
    SECRET_KEY=(a random string, length 50)
    
  2. Armazene o secret no Secret Manager:

Console

  1. No Console do Cloud, acesse a página Secret Manager.

    Acessar a página "Gerenciador de secrets"

  2. Clique em Criar secret.

  3. No campo Nome, use django_settings.

  4. Na caixa de diálogo Fazer upload do arquivo, selecione o arquivo .env armazenado localmente.

  5. Clique em Criar secret.

  6. Em Detalhes de django_settings, anote o número do projeto:

    projects/PROJECTNUM/secrets/django_settings
    
  7. Clique em Adicionar membro.

  8. No campo Novos membros, digite PROJECTNUM-compute@developer.gserviceaccount.com e pressione Enter.

  9. No campo Novos membros, digite PROJECTNUM@cloudbuild.gserviceaccount.com e pressione Enter.

  10. No menu suspenso Papel, selecione Acessador de secrets do Secret Manager.

  11. Clique em Save.

gcloud

  1. Crie um novo secret, django_settings:

    gcloud secrets create django_settings --replication-policy automatic
    
  2. Adicione o arquivo .env como uma versão do secret.

    gcloud secrets versions add django_settings --data-file .env
    
  3. Para confirmar a criação do secret, verifique-o:

    gcloud secrets describe django_settings
    

    Anote o número do projeto:

    projects/PROJECTNUM/secrets/django_settings
    
  4. Conceda acesso ao secret para a conta de serviço do Cloud Run:

    gcloud secrets add-iam-policy-binding django_settings \
        --member serviceAccount:PROJECTNUM-compute@developer.gserviceaccount.com \
        --role roles/secretmanager.secretAccessor
    
  5. Conceda acesso ao secret para a conta de serviço do Cloud Build:

    gcloud secrets add-iam-policy-binding django_settings \
        --member serviceAccount:PROJECTNUM@cloudbuild.gserviceaccount.com \
        --role roles/secretmanager.secretAccessor
    

    Na saída, confirme se bindings lista as duas contas de serviço como membros.

Criar um secret para a senha de administrador do Django

O usuário administrador do Django normalmente é criado executando o comando de gerenciamento interativo createsuperuser.

Neste tutorial, uma migração de dados é usada para criar o usuário administrador, recuperando essa senha do Secret Manager.

Console

  1. No Console do Cloud, acesse a página Secret Manager.
  2. Clique em Criar secret.

  3. No campo Nome, use superuser_password.

  4. No campo Valor do secret, digite uma senha aleatória.

  5. Clique em Criar secret.

  6. Em Detalhes de superuser_password, anote o número do projeto (projects/PROJECTNUM/secrets/superuser_password).

  7. clique em Adicionar membro;

  8. No campo Novos membros, digite PROJECTNUM@cloudbuild.gserviceaccount.com e pressione Enter.

  9. No menu suspenso Papel, selecione Acessador de secrets do Secret Manager.

  10. Clique em Save.

gcloud

  1. Crie um novo secret, superuser_password:

    gcloud secrets create superuser_password --replication-policy automatic
    
  2. Adicione uma senha gerada aleatoriamente como uma versão desse secret:

    cat /dev/urandom | tr -dc 'a-zA-Z0-9' | head -c30 > superuser_password
    
    gcloud secrets versions add superuser_password --data-file superuser_password
    
  3. Conceda acesso ao secret do Cloud Build:

    gcloud secrets add-iam-policy-binding superuser_password \
        --member serviceAccount:PROJECTNUM@cloudbuild.gserviceaccount.com \
        --role roles/secretmanager.secretAccessor
    

    Na saída, confirme se bindings lista apenas o Cloud Build como membro.

Conceder acesso ao Cloud Build para o Cloud SQL

Para que o Cloud Build aplique as migrações do banco de dados, é preciso conceder permissões para que o Cloud Build acesse o Cloud SQL.

Console

  1. No Console do Cloud, acesse a página Gerenciamento de identidade e acesso.

    Acessar a página "Gerenciamento de identidade e acesso"

  2. Para editar a entrada de PROJECTNUM@cloudbuild.gserviceaccount.com, clique em Editar.

  3. Clique em Adicionar outro papel.

  4. Na caixa de diálogo Selecionar um papel, selecione Cliente do Cloud SQL.

  5. Clique em Save.

gcloud

  1. Conceda permissão para que o Cloud Build acesse o Cloud SQL:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member serviceAccount:PROJECTNUM@cloudbuild.gserviceaccount.com \
        --role roles/cloudsql.client
    

Primeira implantação do aplicativo

Com a configuração de serviços de apoio, é possível implantar o serviço Cloud Run.

  1. Usando o cloudmigrate.yaml fornecido, use o Cloud Build para criar a imagem, executar as migrações do banco de dados e preencher os recursos estáticos:

    gcloud builds submit --config cloudmigrate.yaml
        --substitutions _INSTANCE_NAME=INSTANCE_NAME,_REGION=REGION
    

    A primeira versão leva alguns minutos para ser concluída.

  2. Quando a criação for bem-sucedida, implante o serviço Cloud Run pela primeira vez, definindo a região de serviço, a imagem de base e a instância do Cloud SQL conectada:

    gcloud run deploy polls-service \
        --platform managed \
        --region REGION \
        --image gcr.io/PROJECT_ID/polls \
        --add-cloudsql-instances PROJECT_ID:REGION:INSTANCE_NAME \
        --allow-unauthenticated
    

    Será exibida a resposta que mostra a implantação bem-sucedida, com o URL de serviço:

    Service [polls-service] revision [polls-service-00001-tug] has been deployed
    and is serving 100 percent of traffic at https://polls-service--uc.a.run.app
    
  3. Para ver o serviço implantado, acesse o URL do serviço.

    Captura de tela da página de destino do aplicativo de pesquisa.
    Se o URL do serviço mostrar "Você está no índice de pesquisas", o aplicativo Django foi implantado com sucesso.
  4. Para fazer login no administrador do Django, anexe /admin ao URL, faça login com o nome de usuário admin e a senha definida anteriormente.

    Captura de tela do administrador do Django
    Depois de autenticado, o administrador do Django será exibido, mostrando o modelo de perguntas no aplicativo Enquetes.

Como definir permissões mínimas (opcional)

Por padrão, esse serviço é implantado com a conta de serviço de computação padrão. No entanto, em alguns casos, o uso da conta de serviço padrão pode fornecer muitas permissões. Se você quiser ser mais restritivo, será necessário criar sua própria conta de serviço e atribuir apenas as permissões exigidas pelo serviço. As permissões necessárias podem variar de serviço para serviço, dependendo dos recursos usados por um determinado serviço.

Os papéis mínimos do projeto exigidos por este serviço são os seguintes:

  • Chamador do Cloud Run
  • Cliente do Cloud SQL
  • Administrador do Storage, no bucket de mídia
  • Acessador de Secret Manager, no secret de configurações do Django. O acesso ao secret do administrador do Django não é exigido pelo próprio serviço.

Para criar uma conta de serviço com as permissões necessárias, faça o seguinte:

  1. No Cloud Shell, crie uma conta de serviço com os papéis necessários:

    gcloud iam service-accounts create polls-service-account
    SERVICE_ACCOUNT=polls-service-account@PROJECT_ID.iam.gserviceaccount.com
    
    # Cloud Run Invoker
    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member serviceAccount:${SERVICE_ACCOUNT} \
        --role roles/run.Invoker
    
    # Cloud SQL Client
    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member serviceAccount:${SERVICE_ACCOUNT} \
        --role roles/cloudsql.client
    
    # Storage Admin, on the media bucket
    gsutil iam ch \
        serviceAccount:${SERVICE_ACCOUNT}:roles/storage.objectAdmin \
        gs://MEDIA_BUCKET
    
    # Secret Accessor, on the Django settings secret.
    gcloud secrets add-iam-policy-binding django_settings \
        --member serviceAccount:${SERVICE_ACCOUNT} \
        --role roles/secretmanager.secretAccessor
    
  2. Implante o serviço, associando-o à nova conta de serviço:

    gcloud run deploy polls-service \
        --platform managed \
        --region REGION \
        --service-account ${SERVICE_ACCOUNT}
    

Como reimplantar o aplicativo

A preparação inicial e as etapas de implantação eram complexas, mas a reimplantação é relativamente direta.

  1. Execute o script de criação e migração do Cloud Build:

    gcloud builds submit --config cloudmigrate.yaml \
        --substitutions _INSTANCE_NAME=INSTANCE_NAME,_REGION=REGION
    
  2. Implante o serviço, especificando apenas a região e a imagem:

    gcloud run deploy polls-service \
        --platform managed \
        --region REGION \
        --image gcr.io/PROJECT_ID/polls
    

Noções básicas sobre o código

O app de exemplo do Django foi criado com ferramentas padrão do Django. Estes comandos criam o projeto e o aplicativo de pesquisa:

django-admin startproject mysite .
python manage.py startapp polls

As visualizações básicas, os modelos e as configurações de rota foram copiados de Como criar seu primeiro aplicativo Django (Parte 1 e Parte 2).

Secrets do Secret Manager

O arquivo settings.py contém o código que usa a API Secret Manager Python para recuperar a versão mais recente do secret nomeado e extraí-la para o ambiente (usando django-environ):

        import google.auth
        from google.cloud import secretmanager_v1

        _, project = google.auth.default()

        if project:
            client = secretmanager_v1.SecretManagerServiceClient()

            SETTINGS_NAME = os.environ.get("SETTINGS_NAME", "django_settings")
            name = f"projects/{project}/secrets/{SETTINGS_NAME}/versions/latest"
            payload = client.access_secret_version(name=name).payload.data.decode(
                "UTF-8"
            )

    with open(env_file, "w") as f:
        f.write(payload)

env = environ.Env()
env.read_env(env_file)

O django_settings foi usado para armazenar diversos valores de secret para reduzir o número de diferentes secrets que precisavam ser configurados.

Embora o superuser_password possa ter sido criado diretamente na linha de comando, o método baseado em arquivo era usado. Se for gerado a partir da linha de comando, foi usado um cuidado usando head -c para determinar o comprimento da string gerada aleatoriamente, garantindo que não havia caracteres de nova linha no final do arquivo, o que poderia causar problemas quando a senha foi inserida no administrador do Django.

Conexão com o banco de dados

Como o secret django_settings continha uma string de conexão de banco de dados criada especialmente, o auxiliar de banco de dados de django-environ pode ser invocado para atribuir o valor DATABASES:

# Use django-environ to define the connection string
DATABASES = {"default": env.db()}

Em vez de definir valores separados para os componentes das informações de conexão do banco de dados, esse método era usado para definir valores separados.

Estática, armazenada em nuvem

O arquivo settings.py também usa django-storages para integrar o bucket de mídia do Cloud Storage diretamente ao projeto:

# Define static storage via django-storages[google]
GS_BUCKET_NAME = env("GS_BUCKET_NAME")

DEFAULT_FILE_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
STATICFILES_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
GS_DEFAULT_ACL = "publicRead"

Automação com o Cloud Build

O arquivo cloudmigrate.yaml executa não apenas as etapas comuns de criação de imagem (criação da imagem do contêiner e envio da imagem para o registro do contêiner), mas também os comandos migrate e collectstatic do Django. Eles exigem acesso ao banco de dados, que é realizado usando o app-engine-exec-wrapper, um auxiliar do Cloud SQL Proxy:

steps:
  - id: "build image"
    name: "gcr.io/cloud-builders/docker"
    args: ["build", "-t", "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}", "."]

  - id: "push image"
    name: "gcr.io/cloud-builders/docker"
    args: ["push", "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}"]

  - id: "apply migrations"
    name: "gcr.io/google-appengine/exec-wrapper"
    args:
      [
        "-i",
        "gcr.io/$PROJECT_ID/${_SERVICE_NAME}",
        "-s",
        "${PROJECT_ID}:${_REGION}:${_INSTANCE_NAME}",
        "-e",
        "SETTINGS_NAME=${_SECRET_SETTINGS_NAME}",
        "--",
        "python",
        "manage.py",
        "migrate",
      ]

  - id: "collect static"
    name: "gcr.io/google-appengine/exec-wrapper"
    args:
      [
        "-i",
        "gcr.io/$PROJECT_ID/${_SERVICE_NAME}",
        "-s",
        "${PROJECT_ID}:${_REGION}:${_INSTANCE_NAME}",
        "-e",
        "SETTINGS_NAME=${_SECRET_SETTINGS_NAME}",
        "--",
        "python",
        "manage.py",
        "collectstatic",
        "--no-input",
      ]

substitutions:
  _INSTANCE_NAME: django-instance
  _REGION: us-central1
  _SERVICE_NAME: polls-service
  _SECRET_SETTINGS_NAME: django-settings

images:
  - "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}"

Variáveis de substituição são usadas nessa configuração. Se você alterar os valores no arquivo, significa que a sinalização --substitutions pode ser descartada no momento da migração.

Nessa configuração, apenas migrações existentes são aplicadas. Para estender essa configuração para gerar migrações, adicione uma etapa makemigrations.

Para estender a configuração do Cloud Build para incluir a implantação em uma configuração sem precisar executar dois comandos, consulte Implantação contínua do git usando o Cloud Build. Isso exige alterações no IAM, conforme descrito.

Criação de superusuário com migrações de dados

O comando de gerenciamento do Django createsuperuser só pode ser executado de forma interativa, ou seja, quando o usuário puder inserir informações em resposta às solicitações. Embora seja possível usar esse comando com o Cloud SQL Proxy e executar comandos em uma configuração local do Docker, outra maneira é criar o superusuário como uma migração de dados:

import os

from django.db import migrations
from django.db.backends.postgresql.schema import DatabaseSchemaEditor
from django.db.migrations.state import StateApps
import google.auth
from google.cloud import secretmanager_v1

def createsuperuser(apps: StateApps, schema_editor: DatabaseSchemaEditor) -> None:
    """
    Dynamically create an admin user as part of a migration
    Password is pulled from Secret Manger (previously created as part of tutorial)
    """
    if os.getenv("TRAMPOLINE_CI", None):
        admin_password = "test"
    else:
        client = secretmanager_v1.SecretManagerServiceClient()

        # Get project value for identifying current context
        _, project = google.auth.default()

        # Retrieve the previously stored admin password
        PASSWORD_NAME = os.environ.get("PASSWORD_NAME", "superuser_password")
        name = f"projects/{project}/secrets/{PASSWORD_NAME}/versions/latest"
        admin_password = client.access_secret_version(name=name).payload.data.decode(
            "UTF-8"
        )

    # Create a new user using acquired password
    from django.contrib.auth.models import User

    User.objects.create_superuser("admin", password=admin_password)

class Migration(migrations.Migration):

    initial = True

    dependencies = []

    operations = [migrations.RunPython(createsuperuser)]

Limpeza

  1. No Console do Cloud, acesse a página Gerenciar recursos:

    Acessar "Gerenciar recursos"

  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir .
  3. Na caixa de diálogo, digite o ID do projeto e clique em Encerrar para excluí-lo.