Torna al blog

Configurazione di Django con PostgreSQL, Nginx e Gunicorn su Ubuntu 20.04

Configurazione di Django con PostgreSQL, Nginx e Gunicorn su Ubuntu 20.04

Django è un framework per applicazioni web gratuito e open-source scritto in Python. Django è velocissimo, sicuro e altamente scalabile. Nelle mani di uno sviluppatore esperto, Django può creare rapidamente un sito web potente. Può integrarsi perfettamente con i server web più diffusi (Apache, Nginx), e database (MySQL, MariaDB, PostgreSQL, Oracle, e SQLite), ecc. Django gestisce alcuni dei siti web più grandi al mondo come Instagram, Mozilla e NASA. Questa guida mostra come configurare la base di un'applicazione web con l'aiuto di Django con PostgreSQL, Nginx e Gunicorn su Ubuntu 20.04.

Prerequisiti

Questa guida richiede l'esecuzione di un server Ubuntu 20.04 configurato con un firewall di base e un utente non root con privilegi sudo. Dai un'occhiata a questa guida dettagliata su come configurare un server Ubuntu. Segui questo tutorial per configurare un utente non root con privilegi sudo. Puoi anche configurare un firewall Iptables seguendo i passaggi di questa guida.

Installeremo Django all'interno di un ambiente virtuale. Avere un ambiente specifico per il progetto consente una gestione più semplice di più progetti dallo stesso server. Una volta configurati i database e le app, distribuiremo l'application server Gunicorn. Gunicorn sarà l'interfaccia dell'applicazione che traduce le richieste dei client da HTTP in chiamate Python che la nostra applicazione può utilizzare. Successivamente, distribuiremo Nginx davanti a Gunicorn per la sua gestione rapida delle connessioni e le funzionalità di sicurezza facili da implementare.

Installazione dei pacchetti necessari

Per prima cosa, inizia installando tutti i pacchetti necessari. Fortunatamente, tutti questi pacchetti sono direttamente disponibili nei repository ufficiali dei pacchetti di Ubuntu. Apri il terminale e aggiorna la cache dei pacchetti APT:

L'elenco dei pacchetti dipende dal fatto che l'applicazione web utilizzi Python 2 o Python 3. Esegui il comando seguente per installare Django con Python 3:

Django 1.11 LTS è l'ultima versione di Django che supporterà Python 2. Se intendi utilizzare Django con Python 2, installa i seguenti pacchetti:

Database e utente PostgreSQL

Per quanto riguarda la soluzione di database, utilizzeremo PostgreSQL. È un potente sistema di database relazionale a oggetti open-source. PostgreSQL offre affidabilità, robustezza e prestazioni. Per i passaggi dettagliati sulla configurazione di PostgreSQL, consulta questa guida su come configurare PostgreSQL sul server Ubuntu. Per la guida corrente, configureremo un database e un utente dedicati per la nostra applicazione Django.

Per impostazione predefinita, PostgreSQL implementa la "peer authentication" come schema di autenticazione per le connessioni locali. In breve, la "peer authentication" autenticherà l'accesso se il nome utente del sistema operativo dell'utente corrisponde a un nome utente PostgreSQL valido. Durante l'installazione, PostgreSQL ha configurato un utente del sistema operativo postgres per corrispondere all'utente amministratore PostgreSQL postgres. Accedi alla sessione interattiva della shell di PostgreSQL come postgres utilizzando il comando seguente:

Ti troverai nel prompt di PostgreSQL. Il primo passo consiste nel creare un database dedicato per il progetto. A scopo dimostrativo, il database si chiamerà viktor_project:

Il passo successivo consiste nel creare un utente dedicato per il database del progetto. L'utente dovrebbe avere un nome utente sicuro. A scopo dimostrativo, il nome utente sarà viktor_project_user:

Ora modificheremo alcuni parametri:

  • Alcuni parametri di connessione. In breve, non sarà necessario interrogare e impostare i valori corretti ogni volta che viene stabilita una connessione. Migliora notevolmente le prestazioni del database.
  • Codifica predefinita su UTF-8. È una codifica universale e Django se l'aspetta.
  • Schema di isolamento delle transazioni predefinito su “read committed”. Blocca la lettura da transazioni non sottoposte a commit.
  • Fuso orario su UTC.

Tutte queste modifiche ai parametri sono raccomandate dal progetto Django stesso. Per implementare queste modifiche, esegui i seguenti comandi. Non dimenticare di cambiare il nome utente del database con quello corretto:

Cambia l'amministratore del database con l'utente del database dedicato:

Il nostro lavoro con PostgreSQL per ora è terminato. Esci dalla shell interattiva di PostgreSQL:

Exit the PostgreSQL interactive shell

Ambiente virtuale Python

Con il database preparato, ora possiamo concentrarci sulla definizione dei restanti requisiti del progetto. Per una gestione più semplice, creeremo un ambiente virtuale e installeremo lì tutti i requisiti Python. Per generare un ambiente virtuale, abbiamo bisogno di virtualenv. Può essere facilmente installato con pip.

I seguenti comandi aggiorneranno pip e installeranno virtualenv. Per Python 3, esegui i seguenti comandi:

Per Python 2, esegui invece i seguenti comandi:

Una volta che virtualenv è installato, è il momento di creare un ambiente virtuale. Successivamente, crea una directory dedicata per l'ambiente virtuale:

Dopodiché, cambia la directory attiva corrente con la directory dedicata per l'ambiente virtuale:

All'interno della directory, esegui il seguente comando. Lo strumento virtualenv creerà un ambiente virtuale con il nome del progetto:

Creerà una sottodirectory con il nome del progetto. La sottodirectory conterrà una versione locale di Python e pip. Offre la flessibilità di installare e configurare un ambiente Python isolato per il progetto.

Il seguente comando attiverà l'ambiente virtuale:

activate the virtual environment

Il prompt del terminale cambierà indicando che stai operando all'interno di un ambiente virtuale Python. Ora che siamo all'interno dell'ambiente virtuale, installeremo i requisiti Python necessari. Abbiamo bisogno di Django, Gunicorn e psycopg2 (adattatore PostgreSQL). Il seguente comando ordinerà al pip locale di installare i componenti:

Anche se stai usando Python 3, pip è il comando corretto. Questo perché all'interno dell'ambiente virtuale, pip3 è rinominato in pip.

Nuovo progetto Django

Con i componenti Python pronti, possiamo iniziare a lavorare con i file effettivi del progetto Django.

  • Creazione di un progetto Django

La directory del progetto è già creata. Diremo a Django di installare i suoi file lì. Questa procedura genererà una directory di secondo livello contenente il codice effettivo. La directory conterrà anche uno script di gestione. Il punto chiave è che stiamo indicando esplicitamente a Django la directory di destinazione invece di lasciargli decidere la directory in base a quella corrente:

Django creerà il progetto di conseguenza. Ecco alcuni dei file e delle directory importanti su cui ci concentreremo. I nomi delle directory e dei file sono utilizzati in base alla dimostrazione.

  • ~/viktor_project/manage.py: Lo script di gestione del progetto di Django.
  • ~/viktor_project/viktor_project/: È il pacchetto che contiene il progetto Django. Dovrebbe contenere i file __init__.py, settings.py, urls.py, asgi.py e wsgi.py.
  • Regolazione delle impostazioni del progetto

Dopo la creazione del progetto, la prima cosa da fare è regolarne la configurazione. Apri settings.py in un editor di testo:

La prima direttiva che stiamo cercando è ALLOWED_HOSTS. Definisce i server o i nomi di dominio che possono connettersi all'istanza di Django. Se una richiesta in arrivo con un Host header non corrisponde all'elenco di ALLOWED_HOSTS, genererà un'eccezione. È raccomandato da Django per evitare determinati tipi di vulnerabilità di sicurezza:

ALLOWED_HOSTS

La sezione successiva su cui ci concentreremo è DATABASE. Gestisce l'accesso al database. Per impostazione predefinita, contiene la configurazione per il motore di database SQLite. Tuttavia, utilizzeremo il database PostgreSQL per il progetto. Django utilizzerà l'adattatore psycopg2 per comunicare con PostgreSQL:

django 1

Ora, spostati in fondo al file. Aggiungi le seguenti righe per indicare la posizione dei file statici. Aiuta Nginx a gestire le richieste per questi elementi:

static

Il nostro lavoro con settings.py è terminato per ora. Salva il file e chiudi l'editor.

  • Finalizzazione della configurazione iniziale del progetto

Ora possiamo migrare lo schema iniziale del database nel database PostgreSQL dedicato. Esegui il seguente comando:

Successivamente, dobbiamo creare un superuser per il progetto. Per generare un superuser, esegui il seguente comando:

viktor_project

Raccogli tutti i file statici nella posizione specificata in settings.py. I file statici verranno raccolti in una directory separata chiamata “static” all'interno della directory del progetto:

Ora dobbiamo configurare il firewall del server. Se hai seguito la guida alla configurazione del server, hai già UFW configurato e attivato. Creeremo un'eccezione per la porta 8000. Questa è la porta predefinita utilizzata da Django. Consulta questa guida per saperne di più su le basi e l'uso del firewall UFW.

Successivamente, verifica l'azione:

Infine, possiamo testare il server in azione. Avvia il server di sviluppo di Django:

Se la configurazione è andata a buon fine, il server di sviluppo di Django dovrebbe avviarsi e accettare le richieste in arrivo. Apri un browser e vai all'IP/dominio del tuo server sulla porta 8000:

django 2

Dovresti atterrare sulla pagina indice predefinita di Django. Per accedere al pannello di amministrazione, aggiungi /admin all'URL. Il pannello di amministrazione è accessibile solo dal superuser creato in precedenza:

Dopo aver effettuato l'accesso, atterrerai sull'interfaccia di amministrazione predefinita di Django:

django 3

Per ora abbiamo terminato i test. Per arrestare il server, premi “Ctrl + C” dalla finestra del terminale.

  • Test di Gunicorn

Prima di lasciare l'ambiente virtuale, vogliamo assicurarci che Gunicorn possa servire le applicazioni. Il modo per testarlo è utilizzare Gunicorn per caricare il modulo WSGI del progetto.

Il comando Gunicorn si trova all'interno della directory del progetto:

Questo avvierà Gunicorn sulla stessa interfaccia su cui era in esecuzione Django. Possiamo testare nuovamente l'app da un normale browser web. Nota che l'interfaccia di amministrazione non avrà alcuno stile applicato perché Gunicorn non sa ancora come trovare i contenuti CSS statici:

Al termine, premi “Ctrl + C” dalla finestra del terminale per arrestare il server Gunicorn.

  • Uscita dall'ambiente virtuale

La configurazione dell'applicazione Django è terminata. Esegui il seguente comando per uscire dall'ambiente virtuale:

File Socket e Service di Gunicorn

Abbiamo verificato che Gunicorn può interagire con l'applicazione Django. Tuttavia, abbiamo bisogno di un modo più robusto per gestire l'application server. Qui entra in gioco systemd. Systemd è uno dei sistemi di init più popolari disponibili su Linux. Ecco una guida approfondita su come gestire i servizi e le unità di systemd.

Possiamo creare file socket e service per Gunicorn per consentire a systemd di gestirlo come se fosse un servizio. All'avvio, verrà generato il socket di Gunicorn. Il socket rimarrà in ascolto per le connessioni in entrata. Quando si verifica una connessione, systemd avvierà i processi Gunicorn per gestire la connessione.

  • Socket di Gunicorn

Iniziamo creando un socket Gunicorn. Il file deve essere creato con i privilegi di sudo:

Inserisci il seguente codice all'interno del file:

Come puoi vedere, ci sono tre sezioni nel codice.

  • [Unit]: Questa sezione descrive il socket.
  • [Socket]: Definisce la posizione del socket.
  • [Install]: Questa parte assicura che systemd crei il socket al momento giusto.

Salva il file e chiudi l'editor.

  • Servizio Gunicorn

Successivamente, creeremo un file di servizio per Gunicorn. Similmente al file socket, deve essere creato con i privilegi di sudo:

Inserisci il seguente codice:

Il codice contiene diverse sezioni:

  • [Unit]: Questa sezione specifica i metadati e le dipendenze. Descrive anche l'avvio solo dopo il raggiungimento del target di rete.
  • [Service]: Questa sezione specifica l'utente e il gruppo con cui verrà eseguito il processo. La proprietà del gruppo è impostata su “www-data” in modo che Nginx possa comunicare con Gunicorn. Mappa inoltre le directory di lavoro e specifica i comandi di avvio.
  • [Install]: Questa sezione indica a systemd a cosa collegare questo servizio se è abilitato all'avvio. Dovrebbe avviarsi dopo l'avvio del normale sistema multi-utente.

Successivamente, salva il file e chiudi l'editor.

  • Abilitazione del socket Gunicorn

Il socket Gunicorn è pronto per l'uso. Pertanto, puoi eseguire i seguenti comandi. Avvierà e abiliterà il socket. Il file del socket verrà creato in /run/gunicorn.sock all'avvio. Quando viene effettuata una connessione al socket, systemd avvierà il servizio Gunicorn per gestirla:

Verifica lo stato del socket Gunicorn:

Ora, verifica l'esistenza del file del socket:

Se lo stato di systemctl indica un errore o il file gunicorn.sock non è stato trovato, significa che il socket non è stato creato correttamente. Controlla il log dettagliato per trovare indizi:

gunicorn.socket

Non dimenticare di dare un'altra occhiata al gunicorn.socket file per potenziali errori.

  • Attivazione del socket

Finora abbiamo avviato il gunicorn.socket. Tuttavia, senza alcuna richiesta di connessione, gunicorn.service non si attiverà. Successivamente, verifica lo stato di Gunicorn:

Possiamo testare il meccanismo di attivazione del socket inviando una richiesta di connessione utilizzando curl:

Dovresti ricevere un output HTML dall'applicazione. Questo indica che Gunicorn è stato avviato correttamente ed è stato in grado di servire l'applicazione Django. Verifica lo stato attuale del servizio Gunicorn:

In caso di comportamenti o output imprevisti (che indicano un errore), controlla i log dettagliati per trovare indizi:

Se sono state apportate modifiche al file gunicorn.service, è necessario ricaricare il demone per rileggere la definizione del servizio. Richiede anche il riavvio del servizio Gunicorn:

Configurazione di Nginx

Ora configureremo Nginx per passare il traffico in entrata al processo. Innanzitutto, crea un nuovo blocco server in Nginx:

Quindi, inserisci il seguente codice:

 

Ecco diversi blocchi nella configurazione:

  • service: Questo blocco definisce che il server deve ascoltare normalmente sulla porta 80 e deve rispondere al nome di dominio o all'indirizzo IP del server.
  • location: Questa è la prima voce location. Definisce dove trovare gli asset statici.
  • location: Questa è la seconda voce location. Questo blocco definisce i parametri proxy standard e come passare il traffico al socket Gunicorn.

Salva il file e chiudi l'editor. Collega il file alla directory “sites-enabled” per attivarlo:

Successivamente, verifica se ci sono errori di sintassi nella configurazione di Nginx:

Se non hai riscontrato errori, riavvia Nginx per applicare la modifica:

Dobbiamo modificare nuovamente le regole di UFW. Non abbiamo più bisogno dell'accesso al server di sviluppo, quindi possiamo rimuovere l'eccezione per la porta 8000. Inoltre, vogliamo aprire la porta 80 per il traffico normale:

Verifica queste modifiche alle regole del firewall:

Il server dovrebbe ora essere accessibile da un normale browser web.

Procedure di risoluzione dei problemi

Se tutti i passaggi sono stati seguiti correttamente, l'applicazione Django dovrebbe essere accessibile tramite Internet. In caso contrario, significa che l'installazione non è andata come previsto. Dobbiamo procedere alla risoluzione dei problemi per individuare la causa del problema.

  • Nginx mostra la pagina predefinita

Se Nginx mostra la pagina predefinita invece del proxy dell'applicazione, di solito significa che il server_name è stato configurato in modo errato nel blocco server.

In questo esempio, il blocco server è memorizzato nella seguente posizione:

La voce server_name determina quale blocco server Nginx utilizzerà per rispondere alle richieste. Se viene mostrata la pagina predefinita, probabilmente Nginx non è stato in grado di associare la richiesta a un blocco server esplicito, quindi sta ripiegando sul blocco predefinito:

Verifica se il blocco server del tuo progetto Django ha un valore corretto per server_name.

  • 502 Bad Gateway

L'errore 502 indica che Nginx non è riuscito a fungere da proxy per la richiesta con successo. Esiste un'ampia gamma di possibili problemi di configurazione che possono portare all'errore 502, quindi abbiamo bisogno di indizi per risolverlo correttamente.

La fonte principale di indizi sono i log degli errori di Nginx. In genere, indicheranno le condizioni che hanno causato i problemi durante il proxy. Controlla il log degli errori di Nginx utilizzando il seguente comando:

Una volta aperto il log, prova ad accedere nuovamente al server. Dovrebbe generare un nuovo messaggio di errore nel log. Questo può aiutare a restringere il campo del problema. Ecco un paio di possibili messaggi:

  • connect() to unix:/run/gunicorn.sock failed (2: No such file or directory)

Indica che Nginx non è riuscito a trovare gunicorn.sock nella posizione definita nella configurazione. La posizione è descritta dalla direttiva proxy_pass sotto il blocco del sito. Verifica se proxy_pass indica la posizione corretta di gunicorn.sock generato dall'unità systemd gunicorn.socket:

Se gunicorn.sock non è stato trovato nella directory /run, significa che systemd non è riuscito a generarlo. Dovresti ricontrollare i passaggi di configurazione del file socket di Gunicorn.

  • connect() to unix:/run/gunicorn.sock failed (13: Permission denied)

Indica che Nginx non è riuscito a connettersi al socket Gunicorn a causa di problemi di autorizzazione. Ciò può accadere se il processo è stato eseguito come utente root invece di un utente sudo . Sebbene systemd abbia generato gunicorn.sock con successo, Nginx non è in grado di utilizzarlo.

Un possibile colpevole potrebbe essere la limitazione dei permessi tra la directory root (/) e il file gunicorn.sock . Controlla i permessi e la proprietà del file socket e di ciascuna delle sue directory principali:

La prima colonna descrive i permessi del file. La seconda colonna descrive l'utente proprietario e la terza colonna il gruppo proprietario. Se una qualsiasi delle directory che portano a gunicorn.sock non ha i permessi di lettura ed esecuzione appropriati, Nginx non riuscirà ad accedere al socket.

  • Django mostra “could not connect to the server: Connection refused”

Indica che Django non è riuscito a connettersi al server PostgreSQL. Assicurati che il server PostgreSQL sia attivo e funzionante:

Se non è in esecuzione, esegui i seguenti comandi per avviarlo e abilitarlo:

sudo systemctl enable postgresql

Se riscontri ancora questo errore, assicurati che le credenziali del database siano definite correttamente in settings.py:

Ulteriore risoluzione dei problemi

Per un'ulteriore risoluzione dei problemi, sono disponibili vari log. Questi log possono aiutare a restringere le fonti dei problemi.

Ecco un elenco di log che possono essere utili:

  • Log di Nginx
  • Log di accesso-Nginx
  • Log di errore-Nginx
  •  Log dell'applicazione-Gunicorn
  •  Log del socket-Gunicorn
Dopo aver apportato qualsiasi aggiornamento alla configurazione o all'applicazione, potrebbe essere necessario riavviare i processi per applicare le modifiche. Se l'applicazione Django è stata aggiornata, riavvia il processo Gunicorn per applicare le modifiche:
Nel caso in cui vengano apportate modifiche ai file di servizio o socket di Gunicorn, ricarica il demone e riavvia i processi:
Se sono state apportate modifiche alla configurazione del blocco server di Nginx, questa deve essere testata prima di essere messa in funzione. Richiede inoltre il riavvio di Nginx:

Considerazioni finali

Questa guida dimostra con successo come gettare le basi di Django. Django fornisce molti dei componenti comuni di un'applicazione web, consentendoti di concentrarti sugli elementi unici. Il progetto Django funzionerà all'interno dell'ambiente virtuale. Gunicorn gestisce la comunicazione tra le richieste dei client e Django. Infine, Nginx funge da reverse proxy per la gestione delle connessioni dei client.

Buona programmazione!

author

Hark Labs

Autore · CloudSigma

Preslav Dobrev è un designer creativo presso CloudSigma, con un focus su un'identità aziendale coerente attraverso l'uso di canali di marketing tradizionali e innovativi. È abile nel fondere la visione artistica con il marketing strategico per creare narrazioni di brand di grande impatto.

Commenti

Ancora nessun commento. Scrivi il primo.