Esecuzione di Django nell'ambiente Cloud Run

Il deployment di applicazioni stateful in Cloud Run come Django comporta l'integrazione di servizi per interagire tra loro e formare un progetto coeso.

Questo tutorial presuppone che tu abbia familiarità con lo sviluppo web Django. Se non hai mai sviluppato con Django, ti consigliamo di seguire la procedura per scrivere la tua prima app Django prima di continuare.

Sebbene questo tutorial mostri Django in modo specifico, puoi utilizzare questa procedura di deployment con altri framework basati su Django, come Wagtail e Django CMS.

Questo tutorial utilizza Django 5, che richiede almeno Python 3.10.

Obiettivi

In questo tutorial, imparerai a:

  • Crea e connetti un database Cloud SQL.
  • Crea e utilizza i valori dei secret di Secret Manager.
  • Esegui il deployment di un'app Django in Cloud Run.

  • Ospita file statici su Cloud Storage.

  • Utilizza Cloud Build per automatizzare il deployment.

Costi

In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il calcolatore prezzi.

I nuovi utenti di Google Cloud potrebbero avere diritto a una prova senza costi.

Prima di iniziare

  1. Accedi al tuo account Google Cloud . Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti senza costi per l'esecuzione, il test e il deployment dei workload.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the Cloud Run, Cloud SQL, Cloud Build, Secret Manager, Artifact Registry, and Compute Engine APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  5. Installa gcloud CLI.

  6. Se utilizzi un provider di identità (IdP) esterno, devi prima accedere a gcloud CLI con la tua identità federata.

  7. Per inizializzare gcloud CLI, esegui questo comando:

    gcloud init
  8. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  9. Verify that billing is enabled for your Google Cloud project.

  10. Enable the Cloud Run, Cloud SQL, Cloud Build, Secret Manager, Artifact Registry, and Compute Engine APIs.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

  11. Installa gcloud CLI.

  12. Se utilizzi un provider di identità (IdP) esterno, devi prima accedere a gcloud CLI con la tua identità federata.

  13. Per inizializzare gcloud CLI, esegui questo comando:

    gcloud init
  14. Assicurati che l'account utilizzato per questo tutorial disponga di autorizzazioni sufficienti.

prepara l'ambiente

Clona un'app di esempio

Il codice dell'app di esempio Django si trova nel repository GoogleCloudPlatform/python-docs-samples su GitHub.

  1. Puoi scaricare l'esempio come file ZIP ed estrarlo o clonare il repository sulla tua macchina locale:

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
    
  2. Vai alla directory che contiene il codice di esempio:

    Linux/macOS

    cd python-docs-samples/run/django
    

    Windows

    cd python-docs-samples\run\django
    

Conferma la configurazione di Python

Questo tutorial si basa su Python per eseguire l'applicazione di esempio sulla tua macchina. Il codice campione richiede anche l'installazione delle dipendenze

Per maggiori dettagli, consulta la guida all'ambiente di sviluppo Python.

  1. Verifica che Python sia almeno alla versione 3.10.

     python -V
    

    Dovresti visualizzare Python 3.10.0 o un valore superiore.

  2. Crea un ambiente virtuale Python e installa le dipendenze:

    Linux/macOS

    python -m venv venv
    source venv/bin/activate
    pip install --upgrade pip
    pip install -r requirements.txt
    

    Windows

    python -m venv venv
    venv\scripts\activate
    pip install --upgrade pip
    pip install -r requirements.txt
    

Scarica il proxy di autenticazione Cloud SQL per connetterti a Cloud SQL dalla tua macchina locale

Una volta eseguito il deployment, l'app utilizza il proxy di autenticazione Cloud SQL integrato nell'ambiente Cloud Run per comunicare con l'istanza Cloud SQL. Tuttavia, per testare l'app localmente, devi installare e utilizzare una copia locale del proxy nel tuo ambiente di sviluppo. Per ulteriori dettagli, consulta la guida al proxy di autenticazione Cloud SQL.

Il proxy di autenticazione Cloud SQL utilizza l'API Cloud SQL per interagire con l'istanza SQL. Per farlo, è necessaria l'autenticazione dell'applicazione tramite gcloud CLI.

  1. Autenticati e acquisisci le credenziali per l'API:

    gcloud auth application-default login
    
  2. Scarica e installa il proxy di autenticazione Cloud SQL sulla tua macchina locale.

    Linux a 64 bit

    1. Scarica il proxy di autenticazione Cloud SQL:
      curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.21.1/cloud-sql-proxy.linux.amd64
    2. Rendi eseguibile il proxy di autenticazione Cloud SQL:
      chmod +x cloud-sql-proxy

    Linux a 32 bit

    1. Scarica il proxy di autenticazione Cloud SQL:
      curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.21.1/cloud-sql-proxy.linux.386
    2. Se il comando curl non viene trovato, esegui sudo apt install curl e ripeti il comando di download.
    3. Rendi eseguibile il proxy di autenticazione Cloud SQL:
      chmod +x cloud-sql-proxy

    macOS a 64 bit

    1. Scarica il proxy di autenticazione Cloud SQL:
      curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.21.1/cloud-sql-proxy.darwin.amd64
    2. Rendi eseguibile il proxy di autenticazione Cloud SQL:
      chmod +x cloud-sql-proxy

    Mac M1

    1. Scarica il proxy di autenticazione Cloud SQL:
        curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.21.1/cloud-sql-proxy.darwin.arm64
        
    2. Rendi eseguibile il proxy di autenticazione Cloud SQL:
        chmod +x cloud-sql-proxy
        

    Windows a 64 bit

    Fai clic con il tasto destro del mouse su https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.21.1/cloud-sql-proxy.x64.exe e seleziona Salva link con nome per scaricare il proxy di autenticazione Cloud SQL. Rinomina il file in cloud-sql-proxy.exe.

    Windows a 32 bit

    Fai clic con il tasto destro del mouse su https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.21.1/cloud-sql-proxy.x86.exe e seleziona Salva link con nome per scaricare il proxy di autenticazione Cloud SQL. Rinomina il file in cloud-sql-proxy.exe.

    Immagine Docker del proxy di autenticazione Cloud SQL

    Il proxy di autenticazione Cloud SQL ha immagini container diverse, ad esempio distroless, alpine e buster. L'immagine del container del proxy di autenticazione Cloud SQL predefinita utilizza distroless, che non contiene alcuna shell. Se hai bisogno di una shell o di strumenti correlati, scarica un'immagine basata su alpine o buster. Per maggiori informazioni, vedi Immagini container del proxy di autenticazione Cloud SQL.

    Puoi eseguire il pull dell'ultima immagine sulla tua macchina locale utilizzando Docker con il seguente comando:

    docker pull gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.21.1
    

    Altri sistemi operativi

    Per altri sistemi operativi non inclusi qui, puoi compilare il proxy di autenticazione Cloud SQL dal codice sorgente.

    Puoi scegliere di spostare il download in una posizione comune, ad esempio una posizione sul tuo PATH o nella tua home directory. Se scegli di farlo, quando avvii il proxy di autenticazione Cloud SQL più avanti nel tutorial, ricordati di fare riferimento alla località scelta quando utilizzi i comandi cloud-sql-proxy.

Crea servizi di backend

Questo tutorial utilizza diversi servizi Google Cloud per fornire il database, l'archiviazione dei contenuti multimediali e l'archiviazione dei secret che supportano il progetto Django di cui è stato eseguito il deployment. Questi servizi vengono implementati in una regione specifica. Per l'efficienza tra i servizi, tutti i servizi devono essere implementati nella stessa regione. Per saperne di più sulla regione più vicina a te, consulta Prodotti disponibili per regione.

Questo tutorial utilizza i meccanismi di hosting di asset statici integrati in Cloud Run.

Configura un'istanza Cloud SQL per PostgreSQL

Django supporta ufficialmente più database relazionali, ma offre il massimo supporto per PostgreSQL. PostgreSQL è supportato da Cloud SQL, quindi questo tutorial sceglie di utilizzare questo tipo di database.

La sezione seguente descrive la creazione di un'istanza PostgreSQL, di un database e di un utente del database per l'app.

  1. Crea l'istanza PostgreSQL:

    Console

    1. Nella console Google Cloud , vai alla pagina Istanze Cloud SQL.

      Vai alla pagina Istanze Cloud SQL

    2. Fai clic su Crea istanza.

    3. Fai clic su Scegli PostgreSQL.

    4. Per Versione SQL, scegli "Enterprise".

    5. Per Preset versione, scegli "Sandbox".

    6. Nel campo ID istanza, inserisci INSTANCE_NAME.

    7. Inserisci una password per l'utente postgres.

    8. Mantieni i valori predefiniti per gli altri campi.

    9. Fai clic su Crea istanza.

    L'istanza sarà pronta per l'uso dopo qualche minuto.

    gcloud

    • Crea l'istanza PostgreSQL:

      gcloud sql instances create INSTANCE_NAME \
          --project PROJECT_ID \
          --database-version POSTGRES_16 \
          --tier db-n1-standard-2 \
          --region REGION
      

    Sostituisci quanto segue:

    • INSTANCE_NAME: il nome dell'istanza Cloud SQL
    • PROJECT_ID: l' Google Cloud ID progetto
    • REGION: la Google Cloud regione

    La creazione dell'istanza e la sua preparazione all'uso richiedono alcuni minuti.

  2. All'interno dell'istanza creata, crea un database:

    Console

    1. Nella pagina dell'istanza, vai alla scheda Database.
    2. Fai clic su Crea database.
    3. Nella finestra di dialogo Nome database, inserisci DATABASE_NAME.
    4. Fai clic su Crea.

    gcloud

    • Crea il database all'interno dell'istanza appena creata:

      gcloud sql databases create DATABASE_NAME \
          --instance INSTANCE_NAME
      

      Sostituisci DATABASE_NAME con un nome per il database all'interno dell'istanza.

  3. Crea un utente del database:

    Console

    1. Nella pagina dell'istanza, vai alla scheda Utenti.
    2. Fai clic su Aggiungi account utente.
    3. Nella finestra di dialogo Scegli la modalità di autenticazione nella sezione "Autenticazione integrata":
    4. Inserisci il nome utente DATABASE_USERNAME.
    5. Inserisci la password DATABASE_PASSWORD
    6. Fai clic su Aggiungi.

    gcloud

    • Crea l'utente all'interno dell'istanza appena creata:

      gcloud sql users create DATABASE_USERNAME \
          --instance INSTANCE_NAME \
          --password DATABASE_PASSWORD
      

      Sostituisci PASSWORD con una password sicura.

Configura Artifact Registry

Utilizza Artifact Registry per creare un registro in cui archiviare l'immagine container.

Console

  1. Nella console Google Cloud , vai alla pagina Artifact Registry.

    Vai alla pagina Artifact Registry

  2. Fai clic su Crea repository.

  3. Inserisci quanto segue:

    • In Nome, inserisci "cloud-run-source-deploy".
    • Per Formato, seleziona "Docker".
    • In Regione, seleziona REGION.
  4. Mantieni i valori predefiniti per gli altri campi.

  5. Fai clic su Crea.

gcloud

  • Crea un Artifact Registry:
gcloud artifacts repositories create cloud-run-source-deploy \
    --repository-format docker \
    --location REGION

Configura un bucket Cloud Storage

Puoi archiviare gli asset statici inclusi di Django, nonché i contenuti multimediali caricati dagli utenti, in un'archiviazione di oggetti ad alta disponibilità utilizzando Cloud Storage. Il pacchetto django-storages[google] gestisce l'interazione di Django con questo backend di archiviazione.

Console

  1. Nella Google Cloud console, vai alla pagina Cloud Storage.

    Vai alla pagina Cloud Storage

  2. Fai clic su Crea bucket.

  3. Inserisci quanto segue (facendo clic su "Continua" dove necessario):

    • In Nome, inserisci "PROJECT_ID_MEDIA_BUCKET".
    • In Regione, seleziona REGION.
    • Per Classe di archiviazione, mantieni i valori predefiniti.
    • Per Impedisci accesso pubblico, deseleziona "Applica la prevenzione dell'accesso pubblico".
    • In Controllo dell'accesso, seleziona "Granulare".
  4. Mantieni i valori predefiniti per gli altri campi.

  5. Fai clic su Crea.

gcloud

  • Crea un bucket Cloud Storage:

    gcloud storage buckets create gs://PROJECT_ID_MEDIA_BUCKET --location=REGION
    

    Sostituisci MEDIA_BUCKET con un suffisso per il bucket dei contenuti multimediali. Insieme all'ID progetto, questo crea un nome univoco per il bucket.

Archivia i valori dei secret in Secret Manager

Ora che i servizi di backend sono configurati, Django ha bisogno di informazioni su questi servizi. Anziché inserire questi valori direttamente nel codice sorgente Django, questo tutorial utilizza Secret Manager per archiviare queste informazioni in modo sicuro.

Crea il file di ambiente Django come secret di Secret Manager

Memorizzi le impostazioni necessarie per avviare Django in un file ENV protetto. L'app di esempio utilizza l'API Secret Manager per recuperare il valore del secret e il pacchetto django-environ per caricare i valori nell'ambiente Django. Il secret è configurato in modo da essere accessibile da Cloud Run e Cloud Build.

  1. Crea un file denominato .env, definendo la stringa di connessione al database, il nome del bucket dei contenuti multimediali e un nuovo valore SECRET_KEY:

    echo DATABASE_URL=postgres://DATABASE_USERNAME:DATABASE_PASSWORD@//cloudsql/PROJECT_ID:REGION:INSTANCE_NAME/DATABASE_NAME > .env
    echo GS_BUCKET_NAME=PROJECT_ID_MEDIA_BUCKET >> .env
    echo SECRET_KEY=$(cat /dev/urandom | LC_ALL=C tr -dc '[:alpha:]'| fold -w 50 | head -n1) >> .env
    
  2. Archivia il secret in Secret Manager:

    Console

    1. Nella console Google Cloud , vai alla pagina Secret Manager.

      Vai alla pagina Secret Manager

    2. Fai clic su Crea secret.

    3. Nel campo Nome, inserisci django_settings.

    4. Nella finestra di dialogo Valore secret, incolla i contenuti del file .env.

    5. Fai clic su Crea secret.

    6. Elimina il file locale per evitare override delle impostazioni locali.

    gcloud

    1. Crea un nuovo secret, django_settings, con il valore del file .env:

      gcloud secrets create django_settings --data-file .env
      
    2. Elimina il file locale per evitare override delle impostazioni locali:

      rm .env
      
  3. Configura l'accesso al secret:

    Console

    1. In Secret: django_settings, annota il numero del progetto:

      projects/PROJECTNUM/secrets/django_settings
      
    2. Fai clic sulla scheda Autorizzazioni.

    3. Fai clic su Concedi l'accesso.

    4. Nel campo Nuovi membri, inserisci PROJECTNUM-compute@developer.gserviceaccount.com e poi premi Enter.

    5. Nel menu a discesa Ruolo, seleziona Secret Manager Secret Accessor.

    6. Fai clic su Salva.

    gcloud

    1. Recupera il valore del numero di progetto (PROJECTNUM):

      gcloud projects describe PROJECT_ID --format='value(projectNumber)'
    
    1. Concedi l'accesso al secret all'account di servizio Cloud Run:

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

    Nell'output, verifica che bindings elenchi il nuovo account di servizio.

Crea un secret per la password di amministrazione di Django

L'utente amministratore Django viene normalmente creato eseguendo il comando di gestione interattivo createsuperuser.

Questo tutorial utilizza una migrazione dei dati per creare l'utente amministratore, recuperando la password amministratore da Secret Manager.

Console

  1. Nella console Google Cloud , vai alla pagina Secret Manager.
  2. Fai clic su Crea secret.

  3. Nel campo Nome, inserisci superuser_password.

  4. Nel campo Valore secret, inserisci una password casuale e univoca.

  5. Fai clic su Crea secret.

  6. In Dettagli per superuser_password, prendi nota del numero di progetto (projects/PROJECTNUM/secrets/superuser_password).

  7. Fai clic sulla scheda Autorizzazioni.

  8. Fai clic su Aggiungi.

  9. Nel campo Nuovi membri, inserisci PROJECTNUM-compute@developer.gserviceaccount.com e poi premi Enter.

  10. Nel menu a discesa Ruolo, seleziona Secret Manager Secret Accessor.

  11. Fai clic su Salva.

gcloud

  1. Crea un nuovo secret, superuser_password, da una password generata in modo casuale:

    echo -n "$(cat /dev/urandom | LC_ALL=C tr -dc '[:alpha:]'| fold -w 30 | head -n1)" | gcloud secrets create superuser_password --data-file -
    
  2. Concedi l'accesso al secret a Cloud Build:

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

    Nell'output, verifica che bindings elenchi solo Cloud Build come membro.

Esecuzione dell'applicazione nel computer locale

Con i servizi di backend configurati, ora puoi eseguire l'app sul tuo computer. Questa configurazione consente lo sviluppo locale e l'applicazione delle migrazioni del database. Tieni presente che le migrazioni del database vengono applicate anche in Cloud Build, ma devi eseguire questa configurazione locale per makemigrations.

  1. In un terminale separato, avvia il proxy di autenticazione Cloud SQL:

    Linux/macOS

    ./cloud-sql-proxy PROJECT_ID:REGION:INSTANCE_NAME
    

    Windows

    cloud-sql-proxy.exe PROJECT_ID:REGION:INSTANCE_NAME
    

    Questo passaggio stabilisce una connessione dal computer locale all'istanza Cloud SQL a scopo di test locale. Mantieni in esecuzione il proxy di autenticazione Cloud SQL per tutto il tempo in cui testi l'app in locale. L'esecuzione di questo processo in un terminale separato ti consente di continuare a lavorare mentre il processo è in esecuzione.

  2. Nel terminale originale, imposta l'ID progetto localmente (utilizzato dall'API Secret Manager):

    Linux/macOS

    export GOOGLE_CLOUD_PROJECT=PROJECT_ID
    

    Windows

    set GOOGLE_CLOUD_PROJECT=PROJECT_ID
    
  3. Imposta una variabile di ambiente per indicare che stai utilizzando il proxy di autenticazione Cloud SQL (questo valore è riconosciuto nel codice):

    Linux/macOS

    export USE_CLOUD_SQL_AUTH_PROXY=true
    

    Windows

    set USE_CLOUD_SQL_AUTH_PROXY=true
    
  4. Esegui le migrazioni Django per configurare i modelli e gli asset:

    python manage.py makemigrations
    python manage.py makemigrations polls
    python manage.py migrate
    python manage.py collectstatic
    
  5. Avvia il server web Django:

    python manage.py runserver 8080
    
  6. Nel browser, vai alla pagina http://localhost:8080.

    Se ti trovi in Cloud Shell, fai clic sul pulsante Anteprima web e seleziona Anteprima sulla porta 8080.

    Nella pagina viene visualizzato il seguente testo: "Hello, world. Ti trovi nell'indice dei sondaggi". Il server web Django in esecuzione sul tuo computer fornisce le pagine dell'app di esempio.

  7. Premi Ctrl/Cmd+C per arrestare il server web locale.

esegui il deployment dell'app in Cloud Run

Ora che hai configurato i servizi di backend, puoi eseguire il deployment del servizio Cloud Run.

  1. Utilizzando cloudmigrate.yaml fornito, utilizza Cloud Build per creare l'immagine, esegui le migrazioni del database e popola gli asset statici:

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

    Il completamento della prima build richiede alcuni minuti.

  2. Se la build ha esito positivo, esegui il deployment del servizio Cloud Run per la prima volta, impostando la regione del servizio, l'immagine di base e l'istanza Cloud SQL connessa:

    gcloud run deploy polls-service \
        --region REGION \
        --image REGION-docker.pkg.dev/PROJECT_ID/cloud-run-source-deploy/polls-service \
        --add-cloudsql-instances PROJECT_ID:REGION:INSTANCE_NAME \
        --allow-unauthenticated
    

    Dovresti visualizzare un output che mostra che il deployment è riuscito, con un URL del servizio:

    Service [polls-service] revision [polls-service-00001-tug] has been deployed
    and is serving 100 percent of traffic.
    Service URL: https://polls-service-PROJECT_ID.REGION.run.app
    
  3. Aggiorna il servizio agli URL del servizio come variabile di ambiente.

    CLOUDRUN_SERVICE_URLS=$(gcloud run services describe polls-service \
        --region $REGION  \
        --format "value(metadata.annotations[\"run.googleapis.com/urls\"])" | tr -d '"[]')
    
    gcloud run services update polls-service \
        --region REGION \
        --update-env-vars "^##^CLOUDRUN_SERVICE_URLS=$CLOUDRUN_SERVICE_URLS"
    
  4. Per visualizzare il servizio di cui è stato eseguito il deployment, vai all'URL del servizio.

  5. Per accedere all'amministrazione di Django, aggiungi /admin all'URL e accedi con il nome utente admin e la password impostata in precedenza.

    Per recuperare la password di superutente da Secret Manager:

    gcloud secrets versions access latest --secret superuser_password && echo ""
    

Aggiornamento dell'applicazione

Sebbene i passaggi iniziali di provisioning e deployment fossero complessi, l'esecuzione degli aggiornamenti è un processo più semplice:

  1. Esegui lo script di build e migrazione di Cloud Build:

    gcloud builds submit --config cloudmigrate.yaml \
        --substitutions _INSTANCE_NAME=INSTANCE_NAME,_REGION=REGION
    
  2. Esegui il deployment del servizio, specificando solo la regione e l'immagine:

    gcloud run deploy polls-service \
        --region REGION \
        --image REGION-docker.pkg.dev/PROJECT_ID/cloud-run-source-deploy/polls-service
    

Configurazione per la produzione

Ora hai un deployment Django funzionante, ma puoi eseguire ulteriori passaggi per assicurarti che la tua applicazione sia pronta per la produzione.

Disattivare il debug

Verifica che la variabile DEBUG in mysite/settings.py sia impostata su False. In questo modo si impedisce la visualizzazione di pagine di errore dettagliate all'utente, il che può rivelare informazioni sulle configurazioni.

Limita i privilegi dell'utente del database

Gli utenti creati utilizzando Cloud SQL dispongono dei privilegi associati al ruolo cloudsqlsuperuser: CREATEROLE, CREATEDB e LOGIN.

Per impedire all'utente del database Django di disporre di queste autorizzazioni, crea manualmente l'utente in PostgreSQL. Devi aver installato il terminale interattivo psql o utilizzare Cloud Shell, in cui questo strumento è preinstallato.

Console

  1. Nella console Google Cloud , attiva Cloud Shell.

    Attiva Cloud Shell

  2. In Cloud Shell, utilizza il terminale integrato per connetterti all'istanza INSTANCE_NAME:

    gcloud sql connect INSTANCE_NAME --user postgres
    
  3. Inserisci la password dell'utente postgres.

    Ora stai utilizzando psql. Dovresti visualizzare il prompt postgres=>.

  4. Crea un utente:

    CREATE USER DATABASE_USERNAME WITH PASSWORD 'DATABASE_PASSWORD';
    

    Sostituisci PASSWORD con una password univoca e casuale.

  5. Concedi diritti completi sul nuovo database al nuovo utente:

    GRANT ALL PRIVILEGES ON DATABASE DATABASE_NAME TO DATABASE_USERNAME;
    
  6. Uscita psql:

    \q
    

gcloud

  1. Avvia una connessione all'istanza SQL:

    gcloud sql connect INSTANCE_NAME --user postgres
    

    Sostituisci INSTANCE_NAME con l'istanza Cloud SQL creata.

  2. Inserisci la password dell'utente postgres.

    Ora stai utilizzando psql. Dovresti visualizzare il prompt postgres=>.

  3. Crea un utente:

    CREATE USER DATABASE_USERNAME WITH PASSWORD 'DATABASE_PASSWORD';
    
  4. Concedi diritti completi sul nuovo database al nuovo utente:

    GRANT ALL PRIVILEGES ON DATABASE DATABASE_NAME TO DATABASE_USERNAME;
    
  5. Uscita psql:

    \q
    

Impostazione delle autorizzazioni minime

Per impostazione predefinita, questo servizio viene implementato con l'account di servizio Compute predefinito. Tuttavia, in alcuni casi, l'utilizzo del account di servizio predefinito può fornire troppe autorizzazioni. Se vuoi essere più restrittivo, devi creare un tuoaccount di serviziot e assegnare solo le autorizzazioni richieste dal tuo servizio. Le autorizzazioni richieste possono variare da servizio a servizio, a seconda delle risorse utilizzate da un servizio specifico.

I ruoli di progetto minimi richiesti da questo servizio sono i seguenti:

  • Cloud Run Invoker
  • Cloud SQL Client
  • Amministratore Storage nel bucket dei contenuti multimediali
  • Funzione di accesso ai secret di Secret Manager, sul secret delle impostazioni di Django. L'accesso al secret di amministrazione di Django non è richiesto dal servizio stesso.

Per creare un account di servizio con le autorizzazioni richieste e assegnarlo al servizio, esegui questo comando:

  1. In gcloud CLI, crea un service account con i ruoli richiesti:

    gcloud iam service-accounts create polls-service-account
    SERVICE_ACCOUNT=polls-service-account@PROJECT_ID.iam.gserviceaccount.com
    
    # 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
    gcloud storage buckets add-iam-policy-binding gs://MEDIA_BUCKET \
        --member=serviceAccount:${SERVICE_ACCOUNT} \
        --role=roles/storage.objectAdmin
    
    # Secret Accessor, on the Django settings secret.
    gcloud secrets add-iam-policy-binding django_settings \
        --member serviceAccount:${SERVICE_ACCOUNT} \
        --role roles/secretmanager.secretAccessor
    
    # Secret Accessor, on the Django super user password.
    gcloud secrets add-iam-policy-binding superuser_password \
        --member serviceAccount:${SERVICE_ACCOUNT} \
        --role roles/secretmanager.secretAccessor
    
  2. Esegui il deployment del servizio, associandolo al nuovo account di servizio:

    gcloud run services update polls-service \
        --region REGION \
        --service-account ${SERVICE_ACCOUNT}
    
  3. Aggiorna i job Cloud Run in cloudmigrate.yaml in modo che abbiano anche questa impostazione --service-account.

comprendi il codice

Applicazione di esempio

L'app di esempio Django è stata creata utilizzando gli strumenti Django standard. I seguenti comandi creano il progetto e l'app Sondaggi:

django-admin startproject mysite
python manage.py startapp polls

Le visualizzazioni, i modelli e le configurazioni di route di base sono stati copiati da Scrivere la prima app Django (Parte 1 e Parte 2).

Secret di Secret Manager

Il file settings.py contiene codice che utilizza l'API Python di Secret Manager per recuperare l'ultima versione del secret denominato e inserirla nell'ambiente (utilizzando django-environ):

# SECURITY WARNING: don't run with debug turned on in production!
# Change this to "False" when you are ready for production
env = environ.Env(DEBUG=(bool, True))
env_file = os.path.join(BASE_DIR, ".env")

# Attempt to load the Project ID into the environment, safely failing on error.
try:
    _, os.environ["GOOGLE_CLOUD_PROJECT"] = google.auth.default()
except google.auth.exceptions.DefaultCredentialsError:
    pass

if os.path.isfile(env_file):
    # Use a local secret file, if provided

    env.read_env(env_file)
# ...
elif os.environ.get("GOOGLE_CLOUD_PROJECT", None):
    # Pull secrets from Secret Manager
    project_id = os.environ.get("GOOGLE_CLOUD_PROJECT")

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

    env.read_env(io.StringIO(payload))
else:
    raise Exception("No local .env or GOOGLE_CLOUD_PROJECT detected. No secrets found.")

Il secret viene utilizzato per archiviare più valori secret per ridurre il numero di secret diversi da configurare.

Configurazioni CSRF

Django offre una protezione integrata contro gli attacchi Cross-Site Request Forgery (CSRF). A partire da Django 4.0, le modifiche al funzionamento di questa funzionalità fanno sì che sia importante comunicare a Django l'URL di hosting, in modo che possa offrire la migliore protezione per gli utenti che inviano dati.

Fornisci l'URL dell'app come variabile di ambiente nel file settings.py. Questo è il valore utilizzato da Django per le impostazioni pertinenti.

# SECURITY WARNING: It's recommended that you use this when
# running in production. The URLs will be known once you first deploy
# to Cloud Run. This code takes the URLs and converts it to both these settings formats.
CLOUDRUN_SERVICE_URLS = env("CLOUDRUN_SERVICE_URLS", default=None)
if CLOUDRUN_SERVICE_URLS:
    CSRF_TRUSTED_ORIGINS = env("CLOUDRUN_SERVICE_URLS").split(",")
    # Remove the scheme from URLs for ALLOWED_HOSTS
    ALLOWED_HOSTS = [urlparse(url).netloc for url in CSRF_TRUSTED_ORIGINS]

    SECURE_SSL_REDIRECT = True
    SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
else:
    ALLOWED_HOSTS = ["*"]

Override dei secret locali

Se viene trovato un file .env sul file system locale, viene utilizzato al posto del valore di Secret Manager. La creazione di un file .env in locale può essere utile per i test locali (ad es. sviluppo locale rispetto a un database SQLite o altre impostazioni locali).

Connessione al database

Il file settings.py contiene la configurazione del database SQL. Utilizza l'helper env.db() di django-environ per caricare la stringa di connessione impostata in DATABASE_URL nell'impostazione DATABASES.

Quando esegui l'applicazione localmente e utilizzi il proxy di autenticazione Cloud SQL per accedere al database ospitato, il flag USE_CLOUD_SQL_AUTH_PROXY regola le impostazioni del database per utilizzare il proxy.

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

# If the flag as been set, configure to use proxy
if os.getenv("USE_CLOUD_SQL_AUTH_PROXY", None):
    DATABASES["default"]["HOST"] = "127.0.0.1"
    DATABASES["default"]["PORT"] = 5432

Risorsa statica archiviata sul cloud

Il file settings.py utilizza anche django-storages per integrare il bucket multimediale Cloud Storage direttamente nel progetto:

# Define static storage via django-storages[google]
GS_BUCKET_NAME = env("GS_BUCKET_NAME")
STATIC_URL = "/static/"
STORAGES = {
    "default": {
        "BACKEND": "storages.backends.gcloud.GoogleCloudStorage",
    },
    "staticfiles": {
        "BACKEND": "storages.backends.gcloud.GoogleCloudStorage",
    },
}
GS_DEFAULT_ACL = "publicRead"

Automation con Cloud Build

cloudmigrate.yaml gestisce tutti i passaggi necessari per creare una nuova immagine container e utilizzarla per applicare le migrazioni del database.

Questo tutorial sceglie di utilizzare i buildpack per creare l'immagine container e entry point personalizzati nel Procfile per gestire i comandi di gestione. Questi possono poi essere referenziati dai job Cloud Run per eseguire i comandi.

steps:
  - id: "Build Container Image"
    name: gcr.io/k8s-skaffold/pack
    args: ["build", "${_IMAGE_NAME}", "--builder=gcr.io/buildpacks/builder"]

  - id: "Push Container Image"
    name: "gcr.io/cloud-builders/docker"
    args: ["push", "${_IMAGE_NAME}"]

  - id: "Migrate database"
    name: "gcr.io/google.com/cloudsdktool/cloud-sdk"
    entrypoint: /bin/bash
    args:
      - "-c"
      - |
        gcloud run jobs create migrate-job \
          --region ${_REGION} \
          --image ${_IMAGE_NAME} \
          --set-cloudsql-instances ${_CLOUD_SQL_CONNECTION_NAME} \
          --set-env-vars SETTINGS_NAME=${_SECRET_SETTINGS_NAME} \
          --command migrate \
          --execute-now

  - id: "Create superuser"
    name: "gcr.io/google.com/cloudsdktool/cloud-sdk"
    entrypoint: /bin/bash
    args:
      - "-c"
      - |
        gcloud run jobs create superuser-job \
          --region ${_REGION} \
          --image ${_IMAGE_NAME} \
          --set-cloudsql-instances ${_CLOUD_SQL_CONNECTION_NAME} \
          --set-env-vars SETTINGS_NAME=${_SECRET_SETTINGS_NAME} \
          --set-env-vars DJANGO_SUPERUSER_EMAIL=${_ADMIN_EMAIL} \
          --set-secrets DJANGO_SUPERUSER_PASSWORD=${_ADMIN_PASSWORD_NAME}:latest \
          --command createsuperuser \
          --execute-now

options:
  dynamicSubstitutions: true

substitutions:
  _INSTANCE_NAME: django-instance
  _CLOUD_SQL_CONNECTION_NAME: ${PROJECT_ID}:${_REGION}:${_INSTANCE_NAME}
  _REGION: us-central1
  _SERVICE_NAME: polls-service
  _SECRET_SETTINGS_NAME: django_settings
  _ARTIFACT_REGISTRY: cloud-run-source-deploy
  _IMAGE_NAME: ${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_ARTIFACT_REGISTRY}/${_SERVICE_NAME}
  _ADMIN_EMAIL: example@example.com
  _ADMIN_PASSWORD_NAME: superuser_password

images:
  - "${_IMAGE_NAME}"

In questa configurazione vengono utilizzate le variabili di sostituzione.

Creazione di superuser con Cloud Run Jobs

Il comando di gestione Django createsuperuser può essere eseguito in modo non interattivo impostando DJANGO_SUPERUSER_EMAIL e DJANGO_SUPERUSER_PASSWORD.

Questo tutorial sceglie di utilizzare Cloud Run Jobs per eseguire questo comando. Questa operazione viene eseguita aggiungendo una voce personalizzata a Procfile che esegue createsuperuser.

# Create superuser (requires DJANGO_SUPERUSER_PASSWORD and DJANGO_SUPERUSER_EMAIL envvars)
createsuperuser: python manage.py createsuperuser --username admin --noinput || echo "User already exists."

Esegui la pulizia

Per evitare che al tuo Account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.

Elimina il progetto

  1. Nella console Google Cloud , vai alla pagina Gestisci risorse.

    Vai a Gestisci risorse

  2. Nell'elenco dei progetti, seleziona quello che vuoi eliminare, quindi fai clic su Elimina.
  3. Nella finestra di dialogo, digita l'ID del progetto e fai clic su Chiudi per eliminare il progetto.

Passaggi successivi