Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Docker: i nostri servizi in un container a prova di bomba

Se vogliamo gestire un'infrastruttura di servizi replicabile, scalabile e stabile, Docker e LXC sono sicuramente la soluzione giusta.
Se vogliamo gestire un'infrastruttura di servizi replicabile, scalabile e stabile, Docker e LXC sono sicuramente la soluzione giusta.
Link copiato negli appunti

Proprio poco tempo fa abbiamo visto come il provisioning di infrastrutture di development e produzione possa essere reso piú che agevole da una soluzione come Vagrant, che impacchetta tutta la struttura dove viene fatto il deploy di uno o più software in una Box tranquillamente rieseguibile ovunque. Docker non è molto diverso: più o meno il principio è lo stesso, ossia quello della possibilità di replica di un ambiente di test/produzione, ma il software presenta delle differenze a livello di approccio che lo rendono a mio parere più fruibile per certi versi, anche se piú centralizzato.

Figura 1. Il logo di Docker
Il logo di Docker

Le macchine virtuali di Docker vengono chiamate container, e all’interno di un container possiamo inserire qualsiasi cosa: da un intero sistema operativo, ad un pool di applicazioni, fino al singolo servizio, la struttura dei container di Docker è estremamente granulare ed applicabile a qualsiasi livello. Inoltre, la comodità di Docker è che può essere usato in ambienti virtuali (quindi non è un concorrente di Vagrant quanto piuttosto un tool in più per il provisioning e la gestione delle risorse), oppure “bare metal”. Non importa assolutamente il mezzo, il programma funziona ovunque con la stessa metodologia e ugualmente bene.

Iniziare un progetto con Docker

Prima di tutto, una volta installato Docker (che per esempio su Ubuntu viene fornito tramite un pratico repository), dobbiamo averlo a portata di mano nella shell, perciò assicuriamoci di averlo installato nella directory dei binari oppure in qualche posto del filesystem indicizzato da $PATH in Bash. Non appena ci siamo assicurati di poter eseguire il comando docker senza dover specificare a mano il percorso, possiamo provvedere a recuperare il nostro primo container dai repository ufficiali:

$ docker pull ubuntu

Il che ovviamente scaricherà ed “installerà” un sistema operativo basilare, una versione minimale di Ubuntu. Per proseguire, dovremo far eseguire all’interno del container un comando:

$ docker run -i -t ubuntu /bin/bash

In generale, “docker run” ci permette di eseguire comandi all’interno dei container; eseguendo la Bash, di fatto, apriremo una shell all’interno del sistema ospite. Per avere un listato dei container attivi ci basterà dare il seguente comando:

$ docker ps

In questo modo, esattamente come quando eseguiamo “ps”, avremo la lista dei container in esecuzione con il relativo PID. Piuttosto semplice. Una volta che saremo diventati più bravi con questi processi di base, potremo passare a scrivere un Dockerfile per automatizzare queste procedure, come vedremo in seguito.

Container di Docker: gestione e creazione

I container di Docker non possono essere solamente scaricati per l’uso locale, ma possono essere modificati, e ad ogni modifica del nostro container possiamo assegnare un identificativo, in modo da eseguire per ogni task, in ogni momento, il comando all’interno dello snapshot (layer) più adatto alle nostre esigenze. Il funzionamento delle modifiche ai container (e alla ripacchettizzazione) è molto simile a quello di git, dato che assimilando le operazioni i comandi consistono in pull, commit e push.

Per salvare lo stato di un container modificato infatti possiamo dare, ad esempio:

$ docker commit <container_id> <some_name>

Dove per id ovviamente dobbiamo inserire l’id del container, e nella seconda variabile l’identificativo dello snapshot che ci aiuti a distinguere questo stato dagli altri, in modo anche da poterci lavorare facilmente.

Un esempio efficace di questo comando viene dall’handbook di Docker da CLI:

# from: http://docs.docker.io/en/latest/commandline/cli/
$ docker commit c3f279d17e0a SvenDowideit/testimage:version3

Questo, ovviamente, lavorando sulla nostra base già presa e modificata leggermente. Ma se volessimo crearci la nostra personale immagine di partenza per un container di Docker? Possiamo creare un container semplicemente utilizzando debootstrap (o equipollenti similari), come è descritto sul manuale:

$ sudo debootstrap raring raring > /dev/null
$ sudo tar -C raring -c . | sudo docker import - raring
a29c15f1bf7a
$ sudo docker run raring cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=13.04
DISTRIB_CODENAME=raring
DISTRIB_DESCRIPTION="Ubuntu 13.04"

Il procedimento, in pratica, utilizza debootstrap per scompattare un’immagine di Ubuntu 13.04 su disco, e la funzione di import di Docker per trasformare la directory in una immagine incapsulata in un container. Particolarmente utile, specialmente volendo comprimere un intero filesystem e volendo fare qualche esperimento anche con distribuzioni diverse da Ubuntu.

Nel caso in cui avessimo fatto delle modifiche interessanti e volessimo renderle disponibili al mondo, siamo a distanza di un comando dal farlo:

$ docker push <username>/<repo_name>

Attraverso un semplice push, la nostra macchina sarà utilizzabile da tutti. Ovviamente, rimuoviamo impostazioni personali e quant’altro che possa compromettere la nostra sicurezza, prima di compiere questo passo.

Il Dockerfile

Per automatizzare la procedura di creazione e modifica di un container, possiamo utilizzare il Dockerfile, che in realtà è una delle parti fondanti di Docker: attraverso il Dockerfile infatti è possibile non solo fare il deploy istantaneo automatizzato di più istanze e più container, ma è anche possibile eseguire il prvisioning di queste istanze, automatizzando task di gestione del sistema, installazione del software e tanto altro.

Figura 2. Il filesystem di un container Docker, strutturato in layer (fonte: http://docs.docker.io/en/latest/terms/layer/)
Il filesystem di un container docker, strutturato in layer

Di seguito, vediamo un breve esempio tratto dalla documentazione ufficiale, in cui viene messa in piedi una piccola struttura per fornirci un browser (Firefox) immediatamente disponibile su una connessione VNC.

# From: http://docs.docker.io/en/latest/use/builder/#dockerfile-examples
# Firefox over VNC
#
# VERSION               0.3
FROM ubuntu
# make sure the package repository is up to date
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
# Install vnc, xvfb in order to create a 'fake' display and firefox
RUN apt-get install -y x11vnc xvfb firefox
RUN mkdir /.vnc
# Setup a password
RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
# Autostart firefox (might not be the best way, but it does the trick)
RUN bash -c 'echo "firefox" >> /.bashrc'
EXPOSE 5900
CMD    ["x11vnc", "-forever", "-usepw", "-create"]

I Dockerfile contengono istruzioni per la creazione dei container, chiaramente, con un prefisso maiuscolo che indica il tipo di comando. Tra i fondamentali troviamo:

  • FROM: Definisce da quale container partire per la creazione dell’immagine che andiamo a profilare;
  • RUN: Esegue comandi (in genere Bash, ma in realtà di qualsiasi natura, in maniera dipendente dalla shell che abbiamo definito) all’interno della virtual machine;
  • EXPOSE: Specifica le porte da esporre all’esterno per la reperibilità dei servizi in esecuzione all’interno del container.

Repository di container per Docker

In questa overview, finalmente siamo arrivati all’ultima parte: abbiamo visto come fare il push sul central index di Docker, ma nel caso in cui volessimo lavorare maggiormente con i repository? Certamente possiamo fidarci dell’indice centrale, e cercare i container disponibili con il comando:

$ docker search <keyword>

In ogni caso, per tutelare la nostra sicurezza in ambito aziendale, può far comodo un cambio di infrastruttura spostando tutto il servizio di hosting dei contenitori in-house. Per questo, è possibile clonare il repository git dell’indice di Docker per creare un indice privato su un nostro server, decentralizzando totalmente la produzione. La cosa divertente, tra l’altro, è che il servizio relativo al repository viene eseguito, giustappunto, tramite Docker stesso, attraverso il comando:

$ docker run -p 5000 stackbrew/registry

A questo punto, non dobbiamo fare altro che attrezzarci in maniera diversa per il push, modificando all’interno del comando per inviare le modifiche la stringa che consente la definizione dell’host dove si trovano i repository e andando a inserire l’indirizzo del nostro server.

# From: http://docs.docker.io/en/latest/use/workingwithrepository/
$ docker tag 0u812deadbeef localhost.localdomain:5000/repo_name
$ docker push localhost.localdomain:5000/repo_name

Ti consigliamo anche