Ho sentito l'esigenza di automatizzare un po' il processo, avendo sviluppato site4 basata su Luminus. I sorgenti sono sotto controllo di versione in un repository Git locale. Le modifiche sono committate e inviate ad un repository Git remoto nel cloud. L'applicazione, un sito web, gira su un server virtuale.
Luminus è un micro-framework web per Clojure. È costruito su esperienze consolidate di sviluppo web e affidabili librerie dell'ecosistema di Clojure. Clojure è un linguaggio funzionale per la Java Virtual Machine. Clojure è una piccola sfida per chi programma con linguaggi procedurali o ad oggetti, ma credo valga la pena di provare. Le strutture dati immutabili sono uno strumento importante per sviluppare applicazioni concorrenti sicure e scalabili. Alcuni concetti di Clojure sono utili anche quando si torna a programmare con linguaggi non funzionali.
Una volta sviluppata l'applicazione Luminus ho seguito le istruzioni del sito di Luminus per andare on line, configurando un server VPS Linux con Java e Nginx, quest'ultimo come frontend.
Il server è stato configurato per eseguire l'uberjar, l'eseguibile tutto in uno della web app site4, nella directory /opt/deploy
.
L'applicazione può essere avviata, fermata e riavviata tramite il comando standard systemctl.
L'uberjar ha una dimensione superiore a 50MB e può richiedere un bel po' di tempo per trasferirlo al server tramite una comune DSL.
Per evitare di dover ritrasferire tutto l'uberjar per ogni piccolo cambiamento dell'applicazione, ho scelto di assemblare l'uberjar nel server VPS stesso, scaricando i sorgenti dal Git remoto, compilando l'uberjar, procedendo all'installazione nella directory deploy
e riavviando l'applicazione.
Le prime volte ho fatto tutto a mano, poi ho cercato di automatizzare il processo usando Fabric/fabfile.
Fabric è una semplice ma potente alternativa a Chef, Puppet e Ansible per automatizzare il processo di distribuzione.
Ciò di cui avevo bisogno, era di realizzare in Fabric un task deploy
che eseguisse in sequenza i seguenti task
Innanzitutto, ho definito alcune funzioni ausiliarie: app_name
per ottenere il nome dell'applicazione e git_url
per ottenere l'url del repository Git remoto.
env.app_name = 'site4'
env.git_url = 'https://username:password@agitprovider.org/account/%s.git'
def app_name():
return env.app_name
def git_url():
return env.git_url % app_name()
Poi ho definito la funzione source
che verifica se nella directory stage
dell'utente esista il repository Git dell'app, Se esiste, vengono aggiornati i sorgenti altrimenti viene scaricato.
def source():
with cd('stage'):
if exists(app_name()):
with cd(app_name()):
# run('git pull')
run('git pull %s master' % git_url())
else:
run('git clone %s' % git_url())
La funzione build
è piuttosto semplice.
def build():
with cd('stage/%s' % app_name()):
run('lein uberjar')
La funzione stage
prepara il tutto per l'installazione eseguendo una copia di sicurezza del precedente uberjar ed impostando la proprietà del file del nuovo uberjar.
def stage():
with cd('stage'):
# Backup in the 'stage' directory of the current application
sudo('cp -a /opt/deploy/%s.jar %s-rollback.jar' % (app_name(), app_name()))
# Copy in stage of the new application
sudo('cp -a %s/target/uberjar/%s.jar .' % (app_name(), app_name()))
sudo('chown deploy:deploy %s.jar' % app_name())
Tutto è pronto, ecco quindi la funzione install
che copia l'uberjar nella directory deploy e riavvia l'applicazione.
def install():
with cd('stage'):
sudo('cp -a %s.jar /opt/deploy/%s.jar' % (app_name(), app_name()))
sudo('systemctl restart %s' % app_name())
I quattro task descritti finora vengono eseguiti dalla funzione deploy
.
def deploy():
source()
build()
stage()
install()
Qui c'è il sorgente completo del fabfile.py
Quando ho bisogno di installare la nuova versione dell'applicazione inviata al Git repository remoto, eseguo il seguente comando.
fab vps_server.domain.it deploy
Dato che ho configurato questo server nel file config di SSH, posso eseguire
fab -H vps_server deploy
Se necessario, posso eseguire i vari task uno ad uno, per esempio il primo
fab -H vps_server source
controllando così ogni fase della distribuzione.
Questo è tutto!
Spero questo articolo sia stato interessante.
Ciao!!!
Gianni Di Sanzo