Introduzione a Docker

Docker è una piattaforma aperta​ che permette lo sviluppo,​ il t​rasporto ​e l'esecuzione di applicazioni​ tra ambienti differenti.

Introduzione a Docker

Cos’é docker:

Docker puó essere visto come una macchina virtuale leggera o come un ambiente chroot evoluto.​ Permette infatti l’esecuzione dell’applicazione che ci interessa isolandola dal sistema che la circonda senza avere l’overhead di cpu/ram che una macchina virtuale canonica comporta. In altre parole docker è una piattaforma aperta​ che permette lo sviluppo,​ il trasporto e lesecuzione di applicazioni​ tra ambienti differenti.

La necessità:

Quotidianamente abbiamo a che fare con un numero enorme di differenti​ stack​ e framework​ spesso incompatibili tra loro che devono essere eseguiti in un numero ancora più elevato di ambienti software/hardware diversi. Docker risponde a questa necessità: permette di racchiudere in un container lapplicazione​ per renderla trasportabile ed eseguibile indipendentemente​ dall’hardware sul quale gira e dal software che la circonda.

Docker vs VM:

Una applicazione eseguita dentro una macchina virtuale normale comporta l’esecuzione di tutto il sistema operativo virtualizzato (kernel, librerie, etc.) e questo comporta uno spreco di risorse tra le altre cose di cpu e di spazio disco spazio disco. L’applicazione eseguita invece dentro un container​ non comporta questo spreco perchè il processo è eseguito dal docker daemon direttamente nell’host ospitante senza duplicare lo spazio per i files in comune.

Un container ha le peculiarità di una macchina virtuale come

  • isolamento dei processi tra container differenti
  • isolamento dei processi tra il container ed il sistema ospitante
  • un proprio ip privato

Un ulteriore vantaggio di docker nei confronti di una macchina virtuale è che il processo viene lanciato direttamente sulla macchina dove è in esecuzione il docker daemon: eseguendo un “ps aux” sulla macchina server vedremmo il processo del container. Questo significa che il container usa solo la cpu/memoria necessaria a quel processo al contrario di una macchina virtuale che ha tutto il sistema operativo.

Architettura:

 

Docker è composto da e parti:

  • ­ • docker client
  • ­ • docker daemon
  • ­ • registry

Il docker client comunica con il docker deamon e lo istruisce sulle azioni da compiere, quest’ultimo interroga il registry per ottenere l’image da eseguire in un container.

Possiamo paragonare l’image ad un’immagine di un sistema operativo ed il container ad una istanza di quella immagine in esecuzione.

Fondamenti:

I concetti chiave per comprendere appieno docker sono:

  • ­ • Host la macchina che esegue il container
  • ­ • Registry Hub​ repository di image
  • ­ • Image ​gerarchia di file, con meta­data
  • ­ • Container​ contenitore dell'applicazione
  • ­ • Volume ​storage condiviso dal container
  • ­ • Dockerfile​ script per creare l’image

Host:

  • ­ • la macchina sulla quale gira il docker daemon
  • ­ • la sua p​osizione geografica/logica è ininfluente: ​locale o remota, virtuale o fisica
  • • per il docker client non fa nessuna differenza.

Registry Hub:

  • ­  • è il magazzino di image Docker
  • ­  • può essere pubblico o privato
  • ­  • l’hub ufficiale è h​ttps://hub.docker.com/

I c​omandi base​ per interagire con il r​egistry hub ​sono:

  • ­ • docker search ­ cerca una image
  • ­ • docker pull ­ scarica l’image
  • ­ • docker push ­ carica l’image

Image:

  • ­ • gerarchia di file ​contenenti meta­-data con le istruzioni per eseguire il container
  • ­ • usa un filesystem di tipo U​nion ​per aggregare più layer e presentarli come un unico filesystem
  • ­ • strutturato a livelli (l​ayer)​
  • ­ • readonly,​ una volta creato un layer di un’image non posso più modificarlo (ma posso sovrascriverlo con un altro layer)
  • ­ • usata per creare un container
  • ­ • usa meccanismi di cache per il layer
  • • ha un ID univoco
  • ­ • ha uno o più t​ag ​per identificarne la versione, di default è “latest”

I c​omandi base​ per l’i​mage​ sono:

  • ­ • docker images ­ mostra le image presenti nel sistema
  • ­ • docker save ­ salva l'immagine in un archivio tar
  • ­ • docker import ­ crea l'image da un archivio tar
  • ­ • docker build ­ crea l'immagine da un Dockerfile
  • ­ • docker commit ­ crea l'immagine da un container
  • ­ • docker rmi ­ rimuove l'immagine
  • ­ • docker history ­ mostra l'history dell'immagine

Hands on:

→ docker pull ubuntu:14.04.3 14.04.3: Pulling from library/ubuntu

d3a1f33e8a5a: Already exists
c22013c84729: Already exists
d74508fb6632: Already exists
91e54dfb1179: Already exists
Digest: sha256:d2cdab847fabbd73fdbc41cea2b3cb9b3e7d46fcd0a6ecd1e461e2702c76006e Status: Image is up to date for ubuntu:14.04.3

docker pull​ scarica nel nostro sistema l’image di u​buntu ​con tag 1​4.04.3. ​Il tag è un'eticheta che si può aggiungere all'image per rappresentare una versione specifica. Se non si aggiunge il tag in un comando (per esempio “docker pull ubuntu”) di default viene scaricata l’image con tag “latest”. Possiamo applicare più label alla stessa image.

Quando richiediamo una image vediamo che questa è composta da vari layer sovrapposti creati in sequenza dai comandi eseguiti per l’image. In questo modo se 2 image differiscono solo per l’ultima istruzione avranno i layer precedenti in comune o​ccupando solo una volta spazio nel filesystem​ e si differenzieranno solo per l’ultimo.

→ docker images REPOSITORY ubuntu
ubuntu memcached debian
mysql
REPOSITORY	TAG	IMAGE ID	CREATED	VIRTUAL SIZE
ubuntu		14.04.3	91e54dfb1179 	5 weeks ago	188.4MB
ubuntu		14.04	91e54dfb1179 	5 weeks ago	188.4MB
memcached	1.4.24	8937d6d027a4 	2 weeks ago	282.9 MB
debian		8.1	4a5e6db8c069 	5 weeks ago	125.2 MB
mysql		5.6.24	ff78d9bb5f46 	4 months ago	282.9	

docker images ​serve a mostrare le image disponibili nel sistema locale. In questo esempio vediamo che l’image con ID 91e54dfb1179 ha 2 tag ma è a tutti gli effetti la stessa image.

Container:

  • ­l’image in esecuzione, ​contiene la nostra applicazione e tutte le librerie ed i dati necessari a farla girare
  • ­veloce, ​viene eseguito in secondi (al contrario delle normali macchine virtuali)
  • ha un proprio ip
  • ­funziona con il meccanismo di c​opy­-on-­write: ​ogni file è in comune con gli altri
  • container che lo utilizzano e viene occupato ulteriore spazio disco solo nel caso sia sovrascritto
  • ­ espone:
    • p​orte​ per comunicare con il mondo esterno
    • v​olumi​ per salvare i dati
    • e​nv​ possibili variabili ambientali necessarie all’applicazione eseguita all’interno del container

I c​omandi base ​per il c​ontainer​ sono:

  • ­ • docker create ­ crea un container (ma non lo fa partire)
  • ­ • docker run ­ crea e avvia un container
  • ­ • docker stop ­ ferma un container
  • ­ • docker start ­ avvia un container
  • ­ • docker restart ­ riavvia un container
  • ­ • docker rm ­ rimuove un container
  • ­ • docker kill ­ manda SIGKILL al container
  • ­ • docker attach ­ connette ad un container in esecuzione
  • ­ • docker wait ­ aspetta finchè il container non termina
  • • docker exec ­ esegue un comando in un container

Hands on:

→ docker run ­­name my_first_mysql_container ­e MYSQL_ROOT_PASSWORD=toor ­d mysql:5.6.24
4c095cbd35110db9969c06c9f778c70f298f9eefe0f6edeb7d02f4c1ef22a096

Abbiamo eseguito il nostro primo container:

  • • docker run​ crea ed avvia il container
  • ­­• --name​ specifica il nome del container, nel nostro caso “my_first_mysql_container”
  • ­​• -e ​serve a specificare variabili d’ambiente. All’interno del nostro container MYSQL_ROOT_PASSWORD ha valore “toor”
  • -d​ manda in esecuzione il container come demone ritornando al prompt
  • mysql:5.6.24​ l’ultimo parametro è il nome dell’immagine dal quale lanciare il container
→ docker ps CONTAINER ID STATUS 4c095cbd3511 seconds 3306/tcp

docker ps ​visualizza i container in esecuzione nel docker daemon. Aggiungendo l’opzione ­-a v​engono visualizzati invece tutti i container (anche quelli fermi).

docker inspect m​ostra tutte le informazioni relative alla macchina: ip, volumi, link, etc.

→ docker inspect ­­format '{{ .NetworkSettings.IPAddress }}' my_first_mysql_container 172.17.0.3

Il container “my_first_mysql_container” da noi creato ha ip 172.17.0.3 e collegandoci alla porta 3306 troviamo mysql in esecuzione con credenziali root/toor (password specificata con l’opzione ­3). Se ci colleghiamo a quell’ip non usiamo però una utilissima caratteristica di docker: la p​ubblicazione delle porte.​

→ docker stop my_first_mysql_container my_first_mysql_container
→ docker rm ­v my_first_mysql_container my_first_mysql_container

docker stop f​erma il container mentre d​ocker rm r​imuove il container dal docker daemon (­​v p​er rimuovere anche gli eventuali volumi).

→ docker run ­p 3306:3306 ­­name my_first_mysql_container ­e MYSQL_ROOT_PASSWORD=toor ­d mysql:5.6.24 38ca05eb0c0eac0ad9c46e9834e7590048836bc89bafd64e7fc4910757ae76a1

→ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

38ca05eb0c0e mysql:5.6.24 "/entrypoint.sh mysql" 3 seconds ago Up 3 seconds 0.0.0.0:3306­>3306/tcp my_first_mysql_container

-p ​3333:3306 serve a pubblicare nel sistema sul quale gira il docker daemon la specifica porta del container ovvero nello specifico quando ci collegheremo a localhost:3333 risponderà invece il container su 172.17.0.3:3306

L’opzione migliore per far comunicare i container tra di loro è usare il parametro --­​­link

→ docker run ­p 80:80 ­­name apache_php ­­link my_first_mysql_container:db ­d php:5.5.29­apache 3e6bbd188f79aaed53c4825a8f72acde489cd8a4808d2f3958cbcb99e57cd86b

L’image php:5.5.29­apache è una image che contiene solo php ed apache e noi vogliamo anche usare mysql. Specificando il flag ­​­--link m​y_first_mysql_container:db docker permette la comunicazione tra il container appena creato e my_first_mysql_container, inoltre crea un’entry nel file host contenente del container apache_php con l’alias da noi specificato “db” che punterà al nostro container my_first_mysql_container. In questa maniera nel container php sarà possibile usare semplicemente come host “db” per accedere al server mysql.

→ docker run ­p 3307:3306 ­­name mysql_volume ­v /home/andrea/mysql_docker_volume:/var/lib/mysql ­e MYSQL_ROOT_PASSWORD=toor ­d mysql:5.6.24
f4da54a90bb704a5c9533af61223aa465f7c26dda74781ac97aa0f78043dc552

L’opzione -­​v /​home/andrea/mysql_docker_volume:/var/lib/mysql serve a mappare una directory locale ad una directory nel server nello specifico l’esempio mappa la directory dei dati di mysql con il path locale /home/andrea/mysql_docker_volume. Questo permette per esempio di fare un backup veloce del db semplicemente stoppando il container e copiando /home/andrea/mysql_docker_volume.

Nel caso del container php/apache è ancora più utile: possiamo mappare /var/www/html ad un path locale ed avere in pochi secondi un ambiente di sviluppo (L)AMP indipendente dalla macchina che stiamo usando.

Dockerfile:

  • ­ • script che permette la creazione di una image
  • ­ • ogni istruzione crea un layer

 

Hands on:

FROM debian:8.1
MAINTAINER andrea@ibuildings.it

ENV APACHE_DOCUMENTROOT /var/www/html ENV APACHE_RUN_USER www­data
ENV APACHE_RUN_GROUP www­data
ENV APACHE_LOG_DIR /var/log/apache2

ENV APACHE_PID_FILE /var/run/apache2.pid ENV APACHE_RUN_DIR /var/run/apache2 ENV APACHE_LOCK_DIR /var/lock/apache2

RUN export DEBIAN_FRONTEND=noninteractive && \ apt­get update && \
apt­get upgrade ­y ­­no­install­recommends

RUN apt­get install apache2 libapache2­mod­php5 ­y VOLUME ['/var/www/html']

EXPOSE 80
CMD apache2 ­DFOREGROUND

Questo Dockerfile:

  • ­ • crea un’image partendo da (FROM) debian:8.1
  • ­ • imposta il manutentore (MAINTAINER) a a​ndrea@ibuildings.it
  • ­ • imposta alcune variabili d’ambiente che saranno presenti nel container (ENV)
  • ­ • esegue alcuni comandi all’interno (RUN) dell’image di partenza (debian:8.1)
  • ­ • espone il volume “/var/www/html” (VOLUME)
  • ­ • espone la porta 80 (EXPOSE)
  • ­ • esegue il comando “apache2 ­DFOREGROUND” all’avvio del container (RUN)

Eseguendo d​ocker build ­-t php_apache_custom . c​reiamo la nostra immagine che sarà poi disponibile.

→ docker build ­t php_apache_custom .
Sending build context to Docker daemon 2.56 kB Step 0 : FROM debian:8.1

> 4a5e6db8c069

Step 1 : MAINTAINER andrea@ibuildings.it ­­­> Using cache
> 0f0dc80c5321

Step 2 : ENV APACHE_DOCUMENTROOT /var/www/html ­­­> Using cache
> b88f51260f22


Removing intermediate container 23c46f400f79 Step 12 : CMD apache2 ­DFOREGROUND

> Running in f824b599b521

> 34e161c07107
Removing intermediate container f824b599b521 Successfully built 34e161c07107

→ docker images
REPOSITORY TAG IMAGE ID php_apache_custom latest 34e161c07107

Dockerfile docker­entrypoint.sh:

CREATED 4 minutes ago

VIRTUAL SIZE 267.7 MB

È uno s​cript ​che viene eseguito a​ll’avvio del c​ontainer ​passandogli come parametro il CMD specificato nel Dockerfile, viene specificato attraverso l’apposita istruzione ENTRYPOINT nel Dockerfile.

Conclusioni:

Docker​ è uno strumento potente utile sia agli sviluppatori che ai sistemisti:

  • ­ • permette di avere un a​mbiente ​p​ulito,​ s​icuro​ e p​ortabile​ per l’applicazione indipendentemente da dove viene eseguito il container
  •  facilita ​la gestione delle d​ipendenze​ e dei conflitti isolando i container
  • ­ • facilita​ la gestione delle l​ibrerie​ permettendo di averne più versioni differenti in diversi container
  • ­ • riduce/​l​imita​ la preoccupazione per le i​ncompatibilità ​su piattaforme differenti, proprie o del cliente
  • • veloce,​ snello, reset instantaneo
  • ­ • facilita ​il testing, l’integration ed il packaging a​utomatico
  • ­ • elimina ​le d​ifferenze​ tra gli ambienti di sviluppo, test e produzione
  • ­ • risolve ​le p​roblematiche ​di performance, c​osti,​ deployment e portabilità normalmente associate con le VM

In definitiva abbraccia docker: b​uild once run anywhere! 

Realizziamo qualcosa di straordinario insieme!

Siamo consulenti prima che partner, scrivici per sapere quale soluzione si adatta meglio alle tue esigenze. Potremo trovare insieme la soluzione migliore per dare vita ai tuoi progetti.