Docker per Django e Postgres

  • Di
  • 2021-12-02 - 7 minuti
banner

Qualche giorno fa, attraverso un sondaggio sui social, è venuto fuori che Docker e Python visti tramite un approccio pratico sono due tematiche che stanno particolarmente a cuore. E allora perché non approfittarne?

Partiamo con Docker in pratica: come rendere un’applicazione scritta in Django, uno dei più noti framework di Python per creare delle interfacce web, attraverso l’uso di container.

E perché non farlo usando il sito web delle Django Girls Italia?

_Via alla volta di Docker per Django e Postgres!

Requisiti

  • Python 3.x installato
  • Django installato
  • Docker installato

Step 1: progetto Django

In questo caso, andremo ad usare un caso d’uso molto semplice, fornito dal mitico gruppo delle Django Girls Italia (qui il link).

Vediamo insieme i file principali dell’applicazione:

  • La directory principale farà da contenitore per il progetto, ed è quella esterna di djangogirls;
  • manage.py: si tratta di un file che consente di interagire con questo progetto Django in vari modi e di agire come se stessimo utilizzando django-admin;
  • __init__.py: file vuoto che dice a Python che questa directory dovrebbe essere considerata un pacchetto;
  • settings.py: file per la configurazione del progetto;
  • urls.py: in questo file, andremo a specificare le URL che andremo ad esporre; si tratta di una sorta di “indice” del sito basato su Django.

Eseguendo il seguente comando, dovremmo ottenere nel terminale un risultato simile a quello che segue:

> python manage.py runserver

Performing system checks...

System check identified no issues (0 silenced).

You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.

November 23, 2021 - 15:50:53
Django version 3.2, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

In questo modo, hai avviato il server di sviluppo Django, estremamente leggero e scritto esclusivamente in Python (ovviamente!).

Questo perché non vale la pena preoccuparsi in questa dase di utilizzare un server più potente o complesso, ma piuttosto demandiamo questo step a quando saremo pronti per la messa in produzione!

Step 2: definizione del Dockerfile

Ricordiamo: un Dockerfile è un documento di testo che contiene tutti i comandi che un utente potrebbe chiamare sulla riga di comando per assemblare un’immagine; una sorta di ricetta per preparare la nostra applicazione.

In questo caso, lo andremo a creare all’interno della cartella principale del progetto, come mostrato nella figura seguente:

Struttura del progetto DjangoGirls Struttura del progetto DjangoGirls con Docker per Django e Postgres

Il Dockerfile conterrà quindi tutte le istruzioni per far sì che l’applicazione possa essere avviata tramite un container:

FROM python:3

ENV PYTHONUNBUFFERED 1

WORKDIR /app

COPY ./requirements.txt /app/requirements.txt

RUN pip install -r requirements.txt && pip install --upgrade pip

COPY . .

RUN chmod a+x run.sh

CMD ["./run.sh"]

Come prima cosa, andiamo a definire l’immagine di base: in questo caso, tramite l’istruzione FROM, specifichiamo che l’immagine da utilizzare è quella che contiene Python in versione 3.x, basata normalmente sul sistema operativo Alpine (un sistema molto minimal derivato da Ubuntu).

La seconda riga imposta una variabile d’ambiente che assicura che l’output di Python venga inviato direttamente al terminale senza prima memorizzarlo nel buffer; questo garantisce che nessun output venga conservato da qualche parte e mai scritto nel caso in cui l’applicazione Python si arresti in modo anomalo.

Si tratta di una configurazione piuttosto comune quando si ha a che fare con applicazioni Django!

La terza riga permette di configurare la cartella di lavoro all’interno del container su /app: questo vuol dire che il progetto Django verrà copiato e lavorato al suo interno, come mostrato nella riga successiva.

La riga n. 4 che contiene l’istruzione COPY copia il file requirements.txt che contiene i moduli e le relative versioni delle dipendenze di Python da installare: in questo caso, c’è solo Django e molto altro, ma è possibile aggiungervi tutti i moduli necessari.

L’istruzione RUN permette di installare i requisiti specificati nel file appena copiato e procediamo anche con l’aggiornamento di pip: non è necessario, ma tuttavia è consigliato farlo!

Successivamente, copiamo il file chiamato run.sh: grazie a questo file, possiamo aggiungere tutte le operazioni preliminari che ci permetteranno di rendere funzionante il sito in un ambiente di sviluppo (maggiori informazioni sono contenute nel README.md del progetto!).

Le ultime due righe ci permettono di aggiornare i permessi dello script in modo che sia eseguibile (a sta per modificare permesso di esecuzione a tutti gli utenti e gruppi) e poi procediamo con l’esecuzione dello script.

Questo però non basta: il nostro progetto ha bisogno anche di un Postgres. E perché non sfruttare Docker Compose per tirare su entrambi i servizi?

Step 3: configurazione docker-compose.yml

Al suo interno andremo a definire tutti i requisiti necessari per far sì che in prima battuta venga avviato il database, e poi venga tirato su il server per l’applicazione Django.

Il file docker-compose.yml avrà quindi questo aspetto:

version: "3.9"

services:
  db:
    image: postgres
    volumes:
      - ./data/db:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: postgres
      POSTGRES_DB: djangogirls
      POSTGRES_PASSWORD: postgres
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/app
    ports:
      - "8000:8000"
    environment:
      - POSTGRES_NAME=postgres
      - POSTGRES_USER=djangogirls
      - POSTGRES_PASS=postgres
    depends_on:
      - db

Definisco due servizi, uno per il database (chiamato db) e uno per la parte web (chiamato proprio web).

Nella sezione relativa al database, vado a specificare come immagine di base l’ultima di Postgres disponibile nei registry di DockerHub e aggiungo anche le variabili di ambiente che mi permetteranno di creare il database.

Come indicato infatti all’interno del README.md del progetto, sarà necessario creare un database chiamato djangogirls con l’utenza postgres/postgres: andiamo quindi ad indicare questi valori all’interno della proprietà environment.

... 
 db:
    image: postgres
    volumes:
      - ./data/db:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: postgres
      POSTGRES_DB: djangogirls
      POSTGRES_PASSWORD: postgres
...

Per quanto riguarda l’applicazione Django, abbiamo a disposizione un Dockerfile che ne farà la build come abbiamo visto allo step 2: sarà quindi sufficiente indicare la cartella attuale come istruzione per la build.

...
  web:
    build: .
...

Per far sì che la nostra applicazione, una volta modificata, sia persistente, utilizziamo la direttiva volumes in entrambi i servizi: nel primo caso, andrà a salvare le informazioni del database, mentre nel secondo caso userà il codice sorgente specificato sotto /app.

...
db:
    image: postgres
    volumes:
      - ./data/db:/var/lib/postgresql/data
...
web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/app
...

Nella sezione ports indichiamo la porta 8000 come quella su cui il container dev’essere in ascolto e infine specifichiamo il comando di avvio nella sezione command, così come riportato nel README.md: questo avvierà il server di Django.

Questo ci permette di avviare il server che conterrà l’applicazione Django: normalmente, si usa django-admin.

django-admin è infatti lo strumento che offre Django per le attività amministrative; il file manage.py viene creato automaticamente in ogni progetto Django e fa la stessa cosa di django-admin, ma imposta anche la variabile d’ambiente DJANGO_SETTINGS_MODULE in modo che punti al file settings.py del tuo progetto.

Generalmente, quando si lavora su un singolo progetto Django, è più facile usare manage.py rispetto a django-admin. Se devi passare da un file di impostazioni Django a un altro, usa django-admin con DJANGO_SETTINGS_MODULE o l’opzione della riga di comando --settings.

Ultimo, ma non ultimo, la clausola depends_on: questa fa sì che il servizio di Django non si avvii fintanto che il database non è in esecuzione. Piccola nota: questo non lo salverà da eventuali errori: se venisse avviato con dei problemi, la dipendenza sarà comunque soddisfatta!

...
depends_on:
      - db
...

Step 4: run!

E dunque, via col mambo: digitiamo il seguente comando da terminale (che accorcia in un unico comando sia la fase di build che di run dei servizi) e apriamo il browser all’indirizzo localhost:8000 per poter vedere la homepage!

$ docker-compose up --build

Pagina principale della community DjangoGirls Pagina principale della community DjangoGirls

Ce l’hai fatta! Docker per Django e Postgres realizzato in un baleno :)

Disclaimer

Questo caso d’uso è perfetto per un ambiente di sviluppo, ma non per la messa in produzione. In quel caso, è fondamentale utilizzare un web server diverso da quello di default, come Nginx.

Per farlo, è sufficiente (a grandi linee) modificare il comando di esecuzione nel docker-compose.yml per avviare l’applicazione sfruttando un webserver diverso e aggiungere ai servizi Nginx o qualsiasi web server che sia adatto al compito!

Risorse utili

Repository

Link GitHub

Post correlati

Iscriviti al TheRedCode.it Corner

La tecnologia corre, e tu devi correre più veloce per rimanere sempre sul pezzo! 🚀

Riceverai una volta al mese (o anche meno) con codici sconto per partecipare agli eventi del settore, quiz per vincere dei gadget e i recap degli articoli più interessanti pubblicati sul blog

Ci sto!

Partners

Community, aziende e persone che supportano attivamente il blog

Logo di Codemotion
Logo di GrUSP
Logo di Python Milano
Logo di Schrodinger Hat
Logo di Python Biella Group
Logo di Fuzzy Brains
Logo di Django Girls
Logo di Improove
Logo del libro open source
Logo di NgRome

Vuoi diventare #tech content writer? 🖊️

Se vuoi raccontare la tua sul mondo #tech con dei post a tema o vuoi condividere la tua esperienza con la community, sei nel posto giusto! 😉

Manda una mail a collaborazioni[at]theredcode.it con la tua proposta e diventa la prossima penna del blog!

Ma sì, facciamolo!