Gestione e deploy di un progetto django

Negli ultimi tempi alla Otto abbiamo speso del tempo per aggiornare le procedure di gestione e deploy di progetti django, pescando a piene mani dalla miriade di nuovi tool disponibili per la gestione di progetti e workflow.

Un sentito grazie a gp, le idee arrivano spesso da quelle parti, ed il suo apporto nei momenti di difficoltà non manca mai.

Il risultato

Questa volta partiamo dalla fine.
Perché tanto sbattimento, cosa si vuole ottenere di diverso da una gestione "manuale" del progetto?

Quello che vogliamo ottenere, è una procedura semplice ed immediata, che ci permetta di inizializzare un progetto seguendo uno schema collaudato.
La fase di startup di un progetto generalmente porta via molto tempo, è una procedura pallosa e ripetitiva e pertanto soggetta ad errori. Le operazioni da compiere sono sempre le stesse: creazione di un virtualenv, inizializzazione di un progetto django, installazione di librerie esterne, creazione del database, configurazione delle impostazioni del progetto etc...

Con questo metodo vogliamo abbattere questi tempi, in modo da poter dedicare la massima attenzione alle fasi importanti del progetto.

Il progetto inizializzato deve avere le seguenti caratteristiche:

  • contenere al suo interno quei pacchetti, librerie etc... che sono dei must have (almeno per me)
  • essere funzionante e pronto per essere ulteriormente sviluppato in locale
  • essere versionato con git
  • contenere uno script che permetta il setup del sistema remoto in modo automatico
  • contenere dei tool per il deploy e funzionalità correlate

Quello che siamo riusciti ad ottenere soddisfa tutti questi requisiti. Vediamo allora quale sarà ora la procedura per la realizzazione di un progetto django.

$ cookiecutter https://github.com/abidibo/cookiecutter-django
$ cd myproject
$ python myproject/manage.py createsuperuser
$ bin/runserver

Per fare il setup della macchina in remoto:

$ bin/ansible_remote

Per fare il deploy:

$ git commit -a -m "first commit"
$ cd myproject && fab production deploy

Fine. Con questi pochi comandi abbiamo deployato un progetto django in remoto che sarà immediatamente visibile dal web.

Ma ora andiamo vediamo dettagliatamente i vari passaggi.

Startup con cookiecutter e ansible

Cookiecutter è un'utility da linea di comando che permette di creare dei progetti a partire da dei template. La struttura del template deve essere di un certo tipo, potete leggere qui come crearne uno apposta per voi.

Detta in soldoni, cookiecutter vi permette di ricevere in input dall'utente delle informazioni associate a delle variabili descritte nel file cookiecutter.json, ad esempio:

  • nome del progetto
  • descrizione
  • usa django-filer
  • utente remoto
  • ...

e di utilizzare poi queste variabili all'interno dei file del vostro template, oppure nei nomi di file e directory!

Capite quindi che possiamo parametrizzare tutte le parti variabili del progetto, creare uno scheletro neutro, ed ottenere un progetto specifico inizializzato dopo aver risposto ad alcune domande!

Cookiecutter può lavorare direttamente con template hostati su github, per cui il comando che utilizziamo è il seguente:

$ cookiecutter https://github.com/abidibo/cookiecutter-django

Nel nostro caso le domande alle quali rispondere sono le seguenti:

  • project_name: nome del progetto. Default "My New Project"
  • project_description: descrizione del progetto. Default "My New Project description"
  • repo_name: nome del repository (git). Default "[project_name | lower | replace(' ', '-')]"
  • core_name: nome dell'applicazione principale django. Default "[repo_name | replace('-', '_')]"
  • admin: applicazione admin di django. Si puo' scegliere tra: django-suit, django-grappelli, default. Default "default"
  • use_filer: utilizzare oppure no il pacchetto django-filer (gestione di file e directory) [y|n]. Default "n"
  • use_disqus: utilizzare o meno il pacchetto django-disqus [y|n]. Default "n"
  • language_code: language code. Default "en-us"
  • timezone: timezone. Default "Europe/Rome"
  • author: autore del progetto. Default "abidibo"
  • email: email dell'autore del progetto. Default "abidibo@gmail.com"
  • remote_user: utente utilizzato per il deploy su server remoto. Default "[repo_name]"
  • domain: dominio (remoto). Default "www.example.com"
  • remote_root_mysql_pwd: password dell'utente root di mysql in remoto. Default "".
  • db_user: utente per il database in remoto. Default "[remote_user]"
  • db_user_pwd: password dell'utente per il database in remoto. Default ""
  • webapp_dir: percorso assoluto alla directory di deploy (remoto).

Non siamo chiaramente obbligati a rispondere a tutte le domande, soprattutto quelle che riguardano l'impostazione di utenti o parametri in remoto non sono necessarie per la creazione del progetto e la configurazione per lo sviluppo in locale. Tuttavia inserendo subito tali parametri si sarà pronti per eseguire il setup della macchina in remoto e per deployare.

Se tutto va per il meglio, alla fine dovremo ottenre le seguenti cose:

  • una nuova direcotry di nome [repo_name], (che da qui in avanti chiamerò ROOT) contenente il progetto inizializzato
  • tutti i pacchetti di sistema necessari installati
  • tutti i pacchetti python necessari già installati all'interno di un virtualenv interno a ROOT (directory .virtualenv), ed il virtualenv già attivo
  • un nuovo database locale pronto all'uso, con tutte le migrazioni già applicate (in locale utilizziamo l'utente root per il database)
  • un nuovo repository git inizializzato
  • un README contenente le spiegazioni per clonare ed iniziare a contribuire al progetto

Il setup della macchina locale viene effettuato grazie ad ansible. Ansible permette di scrivere script che automatizzano delle operazioni attraverso l'esecuzione di task. E' lui che si preoccupa di installare tutti i pacchetti necessari, creare un virtualenv, installare i pacchetti python, creare un database, inizializzare un repository git etc...

A questo punto possiamo entrare nella nostra ROOT, creare un'utente superuser, lanciare il server di sviluppo django ed ammirare il nostro progetto all'url http://localhost:8000

$ cd myproject
$ python myproject/manage.py createsuperuser
$ bin/runserver

Ho utilizzato un wrapper per il comando runserver in modo che di default venga "bindato" sull'indirizzo 0.0.0.0, così che il sito sia visibile anche da altri dispositivi sulla rete locale utilizzando l'ip della macchina (utile per verificare il layout da mobile ad esempio).

In un paio di minuti siamo pronti per sviluppare in locale.

Setup del server remoto con ansible

Quanto è noioso configurare la macchina in remoto per ospitare un nuovo sito (creazione di utenti, db, virtual host, ...)?

Ora sarà molto pù immediato, infatti ansible consente di eseguire task in remoto, e risulta che, tra l'altro, abbia il dono dell'idempotenza:

$ bin/ansible_remote

Questo comando fa diverse cose:

  • installa i pacchetti necessari (apt-get)
  • installa mysql-server e mette in sicurezza l'installazione.
  • crea un database ed un utente che abbia i giusti privilegi per maneggiarlo
  • crea un nuovo utente
  • crea tutte le directory necessarie per l'applicazione, la gestione delle releases, i file statici, i log... all'interno della [webapp_dir] impostata con cookiecutter
  • crea un file .env che contiene le variabili d'ambiente per le impostazioni di django in remoto
  • installa il compilatore sass
  • installa nginx
  • configura un virtual host e lo attiva
  • copia la pagina "lavori in corso" utilizzata per mettere il sito offline
  • fa un restart di nginx

Il virtual host è configurato in modo che prima di qualunque deploy, oppure quando un file .maintenance è presente nella root dell'applicazione, viene mostrata una pagine di manutenzione.

Ora se visitiamo [domain] col browser dovremmo vedere già online la pagina di manutenzione.

Deploy con fabric

Ci manca solo più una cosa: la possibilità di aggiornare in modo semplice la nostra applicazione online. In questo ci aiuta fabric. L'idea (ed anche qui c'è di mezzo gp) è di rendere questa operazione il meno intrusiva possibile su server remoto, in modo che sia verosimilmente applicabile in ogni situazione.

Il modo più semplice allora è quello di creare un archivio dell'ultima revisione del codice, uploadarlo su remoto, eseguire le operazioni di aggiornamento pacchetti, collectstatic e migrazioni di strutture dati, e riavvio dei servizi.

Tutto questo viene eseguito da un solo comando:

$ cd myproject && fab production deploy

Abbiamo creato però anche altri task che possono essere molto utili e risparmiare tempo:

  • fab production rollback
    permette di ripristinare la penultima release. Questo consente ad esempio di ripristinare immediatamente il sito se si verifica un errore con la nuova release.
  • fab production restart_uwsgi
    fa un restart del servizio uwsgi
  • fab production restart_server
    fa un restart di nginx
  • fab production restart
    riavvia nginx ed uwsgi
  • fab production dump_db_snapshot
    fa un dump del db in produzione e lo scarica nella directory ROOT/backup con il nome della revisione corrente
  • fab production load_db_snapshot
    fa il dump del db in produzione e lo importa nel db locale

In questo modo possiamo eseguire con un semplice comando operazioni che prima ci portavano via tempo e pazienza.

Riassumendo

Utilizzando alcuni tools per l'automazione di operazioni è possibile creare un workflow per lo sviluppo di progetti (in questo caso django) preciso e collaudato, che esegue sempre le stesse operazioni, permette di ridurre i tempi di startup a qualche minuto, e fornisce degli strumenti comodi ed affidabili per mettere in produzione la versione del codice più aggiornata.

Categorie

internet opendata piemonte web jeff php programmazione tutorial curiosita governance vim cucina sviluppo apple hardware imac crisi economia politica torino didattica flash illustrazione ricorrenze lapalisse novita release informazione html5 javascript website musica mootools mercato societa vita lavoro HMI interfaccia utente gino gino-news gino-multimedia modernità usa burocrazia jquery django testing libri nova americana etica impresa solidarietà css comunicazioni trasloco ufficio vita sociale entropia immagini fotografia concorso polymer webcomponents programming crowdfunding progetti finanziamento fallimento opensource deploy otto python