Docker: build automatizzati con Dockerfile e fig

29 luglio 2014

Fabrizio Soppelsa

- RHCE, Autore di Linux&C, Autore di Linux Journal

Abbiamo visto nell’ultimo articolo su Docker come creare un container con un webserver come Apache, e come redirigere il traffico HTTP proveniente all’host a questo container.

Le operazioni che abbiamo svolto manualmente nell’esercizio precedente possono essere automatizzate, usando le capacità native di Docker (usando un Dockerfile) o, meglio, con fig, un tool di orchestrazione rilasciato come software opensource da Orchard, una company specializzata nella rivendita di container Docker.

Iniziamo con il Dockerfile. Un Dockerfile si può paragonare a un Makefile: definendo dei target si possono automatizzare procedure anche molto laboriose, ma invece che compilare sorgenti e linkare codice oggetto, il Dockerfile descrive le operazioni da eseguire in sequenza sul container.

Le stesse operazioni che avevamo realizato nell’esempio di Apache possono essere sintetizzate nel seguente Dockerfile che si spiega da solo:

# DOCKER-VERSION 1.1.2
FROM    webtatic/centos7:base

# Aggiungi EPEL, aggiorna il sistema e installa httpd
RUN     yum -y install http://dl.fedoraproject.org/pub/epel/beta/7/x86_64/epel-release-7-0.2.noarch.rpm
RUN     yum update -y
RUN     yum install -y httpd

# Configura Apache
RUN sed -i 's/^#ServerName www.example.com:80/ServerName www.example.com:80/gi' /etc/httpd/conf/httpd.conf

# Dichiara la porta da esporre e il comando da eseguire
EXPOSE  8000
CMD ["/usr/sbin/httpd", "-DFOREGROUND"]

Una volta scritto il Dockerfile, basta effettuare il build del nostro container con questo comando, assegnando per comodità (-t) un nostro tag mnemonico:

# docker build -t fabrizio/centos7-httpd-auto .

Segue un output più o meno articolato che omettiamo per evitare di esibire l’ovvio, il quale output spiega i passaggi che Docker effettua: per ogni operazione, se non si verificano errori, Docker fa il commit sovrascrivendo il container stesso fino al risultato finale. Quando l’immagine è pronta, avrà un proprio ID e si potrà usare.

Il Dockerfile è comodo per organizzare task ripetitivi, ma è talvolta insufficiente per svolgere operazioni in produzione che hanno bisogno di un qualcosa in più, come la connessione tra contenitori o la definizione di come i container debbano scalare. Per questo Orchard (recentemente acquisita da Docker Inc.) ha sviluppato un tool supplementare, che ha chiamato fig, con il quale si possono orchestrare deployment di servizi anche molto complessi, costituiti per esempio da più di un container alla volta (come ad esempio un frontend web e un database server).

Fig non ha un pacchetto RPM, ma si può installare semplicemente scaricando lo script in un path di sistema e assegnandogli i permessi di esecuzione:

# curl -L https://github.com/orchardup/fig/releases/download/0.5.1/linux > /usr/local/bin/fig
# chmod +x /usr/local/bin/fig

Fig incapsula operazioni Docker più ad alto livello, a partire da un file di configurazione denominato fig.yml, con il quale si possono programmare i task necessari al deployment anche multicontainer e/o scalarlo (nel senso che si possono definire quanti container dedicare a servizio, sempre nel caso di web e db, per esempio 3 frontend e 2 db: fig scale web=3 db=2).

Quel che rende fig interessante è la velocità con il quale si può rilasciare un servizio altrimenti realizzabile solo combinando più Dockerfile e script custom. Come realizzare in un comando un hosting WordPress su due container, uno con PHP, e uno con MySQL? Con fig! Intanto scarichiamo l’ultima release di WordPress e creiamo il file fig.yml:

# cd /srv/www/; wget http://wordpress.org/latest.zip
# unzip latest.zip; cd wordpress
# touch fig.yml

Ora bisogna descrivere come dovranno essere costruiti i due container. Ecco il file fig.yml, che assomiglia vagamente a un Dockerfile, a parte il fatto che essendo un file YAML deve essere indentato, con alcune direttive che vediamo nel dettaglio sotto.

web:
  image: orchardup/php5
  command: php -S 0.0.0.0:8000 -t /code
  ports:
    - "8000:8000"
  links:
    - db
  volumes:
    - .:/code
db:
  image: orchardup/mysql
  environment:
    MYSQL_DATABASE: wordpress

Il servizio db fa pull di un mysql pronto ed imposta una variabile d’ambiente. Invece, web, che deriva da un’immagine che contiene PHP pronto, espone e fa PAT (ports) della porta 8000 dall’host al container, importa (volumes) il codice sorgente della directory attuale (.) che contiene wordpress nella directory /code del container, e lo collega via network (links) all’host db.

Creata questa configurazione e configurato WordPress nel famoso wp-config.php, siamo pronti a costruire il nostro piccolo servizio dockerizzato:

# fig up

Quando il comando terminerà, saranno state create e saranno running due immagini Docker che corrispondono ai nostri scopi:

Screen Shot 2014-07-28 at 23.19.23

Se accediamo alla porta 8000 sull’host con il servizio Docker attivo, verremo rediretti al login WordPress, che è in funzione sul container:

Screen Shot 2014-07-28 at 23.24.22

Visto, che carino? Buon lavoro con Docker, ed è il caso di dirlo, viva fig!