Docker 101

Table of Contents

1. Introducció a la Virtualització

Possibles objectius i avantatges de la virtualització:

  • Amortització / reducció de costos del maquinari.
  • Atomicitat / simplicitat dels sistemes.
  • Aïllament dels sistemes.
  • Independència total del maquinari, sempre que el hypervisor sigui compatible amb totes les parts.
  • Possibilitat de fer proves sense "embrutar" el sistema.
  • Facilitat de re-ubicació.

1.1. Virtualització complerta

Mitjançant un hypervisor es simula un maquinari virtual on s'instal·la un sistema operatiu i els serveis que interessi.

En la següent imatge podem veure els diferents tipus de hypervisors on el 2 és el tipus que utilitzem a classe (VirtualBox, VMWare, etc).

Two-Types-of-Hypervisors.png

1.2. Virtualització a nivell de Sistema Operatiu

A la virtualització a nivell de Sistema Operatiu, realment no es fa una virtualització sinó que s'aillen els processos, recursos, etc de manera que els contenidors o aplicacions "virtualitzades" tan sols tenen accés a certes àrees restingides del equip i S.O. anfitrió, fins i tot creant còpies en memòria pròpies de llibreries i executables.

Això implica que ja no cal un hypervisor que simuli o presenti una capa de maquinari virtual, i també que no és necessari instal·lar un S.O. i/o aplicatius genèrics en els contenidors, ja que poden utilitzar els del sistema host.

En resum:

  • S'aïlla en tots els aspectes els contenidors.
  • No es simula maquinari.
  • Es comparteix llibreries, binaris, etc del sistema host.

En la següent mostra les diferències de capes entre Sistemes Virtuals Complerts utilitzant diferents hypervisors i els contenidor Linux.

hyp2.png

Les avantatges inmediates que presenta aquesta forma de "virtualitzar" son:

  • Reducció del pes dels contenidors (no necessari instal·lar un S.O. per cada VM).
  • Reutilització de llibreries i binaris.
  • Velocitat de funcionament dels contenidors (apagat, inici, etc).
  • Manteniment de la major part de les avantatges de la virtualització.

Les desavantatges:

  • En compartir el Kernel, cal que contenidors i sistema host comparteixin arquitectura.

1.2.1. Eines a Linux

Linux presenta certes avantatges per realitzar virtualització a nivell de S.O. ja que ha heretat de Unix dos components que realitzen totes les tasques d'aïllament de processos i ús de recursos del sistema: namespaces i cgourps.

Cal remarcar però que aquestes eines no s'utilitzen exclusivament per a la creació de contenidors, sinó que això és una derivada. És a dir, aquestes eines tenen fucnionalitat per elles mateixes i ens permeten per exemple crear una interfície de xarxa virtual, limitar els recursos utilitzats per un determinat procés (CPU, RAM, …) i un llarg etcètera.

namespaces
Permet la separació dels recursos del Kernel, com punts de muntatge, processos, la xarxa, etc.
cgroups
Permet limitar els recursos utilitzats per un procés (memòria), priorització de l'ús de la CPU, i algunes funcions més.

1.2.2. LXC

LXC és l'implementació de LinuX Containers, una tecnología de virtualització a nivell de sistema operatiu per a S.O. GNU Linu.

Es basa en les eines de cgroups i namespaces vistos i permet virtualitzar utlitzant molt pocs recursos.

1.2.3. Docker

És un projecte de codi obert per a l'automatització del desplegament de contenidors Linux. Això implica que utilitza per sota cgroups i namespaces de la mateixa manera que LXC. Tanmateix aplica varies capes d'abstracció per a millorar l'operativitat amb els contenidors.

Per les seves pecualiritats Docker s'ha anat enfocant més cap a la virtualització de servies o micro-serveis més qu no pas a la virtualització de sistemes sencers. A continuació s'inclou una petita descripció dels seus components principals:

Docker
Eina bàsica del paquet, que permet l'ús d'imatges i contenidors.
Imatge
Plantilla d'un contenidor, és estàtica i no permet canvis.
Contenidor
Materialització d'una imatge. Se'n poden crear tants com es vulguin, aturar-los, reiniciar-los, etc. Cal notar que no comparteixen informació entre si, tot i que puguin ser creats des de la mateixa imatge. També cal notar que si s'eliminen, la informació que contenien es perd. Per aquests motius els contenidors estan enfocats a no emmagatzemar dades.
Volum
Espai del sistema de fitxers del host accessible des de un contenidor i destinat a oferir permanència de les dades i compartició entre contenidors.
Docker Hub
És un repositori d'imatges on podem cercar i descarregar imatges ja fetes que ens serveixin per a llançar els nostres contenidors o crear les nostres pròpies imatges.
Docker File
Arxiu que conté la declaració o construcció d'una imatge. És un dels dos mètodes per crear imatges noves i/o personalitzades. L'altre mètode és crear una imatge des de un contenidor en funcionament.
Docker Compose
Arxiu que permet especificar un conjunt de contenidors, volums, xarxes, etc i les relacions entre ells. S'utilitzen per definir i desplegar estructures complexes de contenidors de forma simplificada.
Docker Swarm
Eina per a la creació i gestió de clústers de Docker. Implementa per si sol moltes coses, com per exemple service discovery i alta disponibilitat.

2. Primers passos amb Docker

2.1. Instal·lació a Debian

L'instal·lació de Docker a Debian a anat canviant al llarg de les versions. Per tant el més recomanable és consutlar la documentació oficial referent a l'insta·lació a Debian.

2.2. Docker Hub

Docker Hub constitueix un repositori públic d'imatges Docker on tant companyies oficials com particular pengen imatges que cobreixen molts casos d'ús. Cercant en aquest repositori podem trobar i aprofitar la feina feta per altres.

Tot i que hem de pensar que la major part d'imatges son segures, quan utilitzem Docker en un entorn sensible (com per exemple la feina) cal recordar que ningú assegura ni es responsabilitza les les imatges de Docker Hub a menys que siguin "oficials". Per tant hem de vigilar amb què descarreguem. Molts cops podem veure el Docker File de la imatge, que ens pot ajudar a assegurar què farà el contenidor.

Per tant es recomana que, sempre que sigui possible, ens creem les nostres pròpies imatges per assegurar que no hi han dobles intencions. Aquestes imatges personalitzades les podem pujar a Docker Hub (i seran públiques a menys que paguem) o ens podem crear el nostre propi repositori estil Docker Hub totalment privat.

En resum, al cercar una imatge a Docker Hub hem d'estar atents a:

  • Si és una imatge oficial o no.
  • Arquitectura per a la que està feta (arm, arm64, x86-64, etc).
  • Les seves descàrregues, tot i que no és un gran indicador de confiança, serà més confiable una imatge amb 5M de descàrregues que una amb 30.
  • El numero de l'última versió de l'imatge. Cal tenir present que es manté històric de versions per cada imatge.

Alguns exemples interessants / curiosos d'imatges que podem trobar son:

pihole
Imatge de Pi-hole un projecte per muntar un server DNS intern que filtri publicitat, per arm.
mysql
Imatge oficial de MySQL Server.
ngnix
Servidor web ngnix, però compte no és oficial sinó que l'ha fet "un particular".
Debian
Imatge oficial de Debian, útil com a base per altres imatges.
Minecraft Srv
Servidor de Minecraft, no oficial.

2.2.1. Cercar imatges a Docker Hub

Cercar imatges es pot realitzar fàcilment amb un navegador visitant la web de Docker Hub i utilitzant el seu cercador.

Des de terminal també ho podem fer mitjançant la comanda:

docker search [opcions] <imatge>

2.2.2. Descarregar imatges de Docker Hub

Per descarregar una imatge, haurem d'executar la comanda:

docker pull <usuari_creador/nom_imatge>[:versió]

Alternativament podem llançar directament un contenidor de la imatge que volem descarregar i si no la tenim descarregada docker la cercarà a Docker Hub de forma automàtica.

docker container run [opcions] <usuari_creador/nom_imatge>[:versió]

En l'opció de la versió de la imatge podem especificar una versió concreta, si no diem res descarregarem la versió latest. Aquesta versió és l'última que s'ha pujat però això dona problemes al mantenir contenidors al llarg del temps.

Si hem descarregat la versió latest d'un Apache per exemple, i el mantenidor de l'imatge al cap d'un temps l'actualitza a una nova versió el que passarà serà el següent:

  • Les imatges descarregades no s'actualitzen.
  • Si intentem tornar a descarregar l'apache latest no farà res perquè ja tenim una versió "amb aquest nom".
  • Caldrà forçar la descàrrega de la nova versió indicant en la comanda pull o run el número de versió a descarregar.

Per tot això és molt recomanable no utilitzar la versió latest i descarregar les imatges indicant en número de versió concret.

Durant la descàrrega és interessant fixar-nos que apareixen varies descàrregues en paral·lel. Això ve determinat per com s'ha construir aquella imatge, ja que es poden definir varies "capes" d'imatge de manera que siguin independents. Al ser capes independents això permet entre altres coses re-aprofitar-les entre imatges diferents, que els canvis en un capa no afectin a la resta, etc. Aquest és un concepte molt interessant de Docker i que veurem més a fons alhora de crear imatges amb Docker File.

dockerpull.gif En aquest gif podem observar la descàrrega per defecte de l'imatge oficial d'un servidor Apache. Destacar:

Versió
Per defecte ens descarrega la imatge amb l'etiqueta de versió latest. Recordeu que tan sols és una etiqueta.
Capes
La imatge consta de 5 capes. Si tinguéssim accés al Docker File i l'analitzéssim veuríem a què correspon cada capa.
Pes
La descàrrega de l'imatge ronda les 60Mb.

2.2.3. Pujar imatges a Docker Hub

Podem pujar les imatges que creem / modifiquem a Docker Hub. Cal tenir present que necessitarem un compte a Docker Hub i que el nostre repositori, a menys que paguem, serà públic.

Per pujar una imatge que tinguem en local ens caldrà executar:

docker push <el_teu_usuari_dockerhub>/<nom_imatge>[:versió]

2.3. Hello World!

En la mateixa línia que els llenguatges de programació Docker proporciona una imatge anomenada "Hello World!" que simplement crea un contenidor que imprimeix per pantalla aquest famós missatge. Tot i la simplicitat, ens pot ser útil per practicar la descàrrega, creació de contenidors i execució dels mateixos.

Per fer-ho tot plegat cal executar:

docker run hello-world

Al executar-ho obtindrem aquest resultat: dockerhelloworld.gif Cal notar les següents coses:

  • No hem utilitzat la comanda docker pull sinó docker run, que a part de descarregar l'imatge (en cas necessari) també crea un contenidor i l'executa.
  • Com que no teníem l'imatge de hello-world, docker automàticament l'ha cercat a Docker Hub i se l'ha descarregat.
  • Al no especificar tag o versió, s'ha descarregat la latest.
  • Tot i que hi han comandes per crear contenidors sense executar-los, la comanda docker run crea el contenidor i l'executa automàticament.
  • El contenidor tan sols tenia una tasca que era imprimir per pantalla, per tant en acabar s'ha parat.

Per acabar amb aquest primer contacte amb Docker podem llistar els contenidors i les imatges que tenim.

Per llistar els contenidors (tots)
docker container ls -a
Per llistar les imatges descarregades
docker image ls

3. Ús de Docker

3.1. Imatges

Com ja hem explicat amb anterioritat, les imatges de Docker constitueixen la plantilla a partir de la qual crearem i executarem els nostres contenidors.

La gestió d'aquestes imatges és molt senzilla. La comanda base és docker image i a partir d'aquí es despleguen varies opcions, tal com indica l'ajuda:

Usage:	docker image COMMAND

Manage images

Commands:
  build       Build an image from a Dockerfile
  history     Show the history of an image
  import      Import the contents from a tarball to create a filesystem image
  inspect     Display detailed information on one or more images
  load        Load an image from a tar archive or STDIN
  ls          List images
  prune       Remove unused images
  pull        Pull an image or a repository from a registry
  push        Push an image or a repository to a registry
  rm          Remove one or more images
  save        Save one or more images to a tar archive (streamed to STDOUT by default)
  tag         Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE

De totes aquestes comandes, les que més utilitzarem son:

ls
Per llistar les imatges locals.
pull
Per descarregar noves imatges de Docker Hub.
rm
Per eliminar imatges que ja no utilitzem.

dockerImage.gif

3.2. Contenidors

Recordem que els contenidors son el resultat d'executar una imatge, és a dir, son la materialització de la mateixa, el que realment s'acaba executant.

Per tant, a partir d'una imatge poden tenir varis contenidors, tots iguals, funcionant. Tanmateix, al llarg de la vida del contenidor, aquest acumularà dades internament (logs, temporals, etc) que recordem no comparteix amb altres contenidors iguals i a més D'Eliminar-ne quan desaparegui el contenidor.

Per a la gestió de contenidors utilitzarem la comanda base docker container i les opcions son:

Usage:	docker container COMMAND

Manage containers

Commands:
  attach      Attach local standard input, output, and error streams to a running container
  commit      Create a new image from a container's changes
  cp          Copy files/folders between a container and the local filesystem
  create      Create a new container
  diff        Inspect changes to files or directories on a container's filesystem
  exec        Run a command in a running container
  export      Export a container's filesystem as a tar archive
  inspect     Display detailed information on one or more containers
  kill        Kill one or more running containers
  logs        Fetch the logs of a container
  ls          List containers
  pause       Pause all processes within one or more containers
  port        List port mappings or a specific mapping for the container
  prune       Remove all stopped containers
  rename      Rename a container
  restart     Restart one or more containers
  rm          Remove one or more containers
  run         Run a command in a new container
  start       Start one or more stopped containers
  stats       Display a live stream of container(s) resource usage statistics
  stop        Stop one or more running containers
  top         Display the running processes of a container
  unpause     Unpause all processes within one or more containers
  update      Update configuration of one or more containers
  wait        Block until one or more containers stop, then print their exit codes

Com podem veure aquí les opcions ja son bastantes, i n'hi han moltes de interessants. Tanmateix com a introducció utilitzarem:

exec
Per executar una comanda dins del contenidor, molt útil per obrir una shell.
logs
per veure els logs del contenidor, sense haver d'entrar.
ls
Per llistar els contenidors que tenim.
port
Per exposar ports del contenidor (fer-los accessibles).
rm
Per eliminar un contenidor.
run / start / stop
Per canviar l'estat d'execució d'un contenidor.

3.2.1. Volums

Com ja hem comentat anteriorment, els volums són la forma que ens dóna Doctor per guardar les dades fora d'un contenidor de manera que quan aquest es pari o sigui eliminat puguem "salvar-les" o compartir-les. Combinat amb sistemes com GlusterFS ens permetria tenir assegurada la disponibilitat i integritat de les dades dins d'un entorn de Docker Swarm.

Per utilitzar-los és molt simple, tan sols alhora de crear un contenidor hem d'incloure l'opció -v. Aquesta té el format següent:

-v <path_local>:<path_contenidor>[:ro]

La utilitat d'aquest element és molt amplia, des de guardar les dades d'un contenidor, tenir en local els arxius de configuració del servei (de manera que els puguem modificar i guardar, independent del contenidor), tenir el local el codi font del script de Python que constitueix el servei, tenir en local els HTMLs i PHP que constitueixen la web que ofereix el contenidor, etc.

Així doncs fixeu-vos que si per exemple estem servint una web basada en Jekyll mitjançant un container (com és el cas d'Alquímia Binària) el contenidor tan sols serà un servidor web, pràcticament per defecte, i podrem tenim en un volum els arxius HTML que hem de servir. D'aquesta manera si l'autor del web vol penjar un nou pot tan sols l'ha d'afegir al directori local corresponent. Això permetrà que les dades que serveix el nostre servidor web siguin independents del servei en si mateix. El paràmetre seria quelcom com això: -v /blog/:/var/www/html/ on vinculem el directori local /blog/ amb el directori del contenidor /var/www/html/. Finalment fixeu-vos que de manera opcional podeu afegir al fina :ro per indicar que s'ha de muntar aquest directori en el contenidor en forma de read only de manera que ni tan sols el susuari root del contenidor podrà escriure res en aquest directori. Molt interessant a nivell de seguretat.

3.2.2. Xarxes

Referent a les xarxes veurem dues coses molt bàsiques:

  • Exposar ports.
  • Assignar IP a un contenidor.

Cal fer notar aquí que Docker permet una gestió molt profunda i complexa de les xarxes, aquí tan sols veurem la punta del iceberg, i el seu ús més habitual.

  1. Exposició de ports

    Primer de tot comentar que si no modifiquem l'assignació de ports, Docker assigna una IP "interna" al contenidor, que no és accessible fora de Docker. Tanmateix si que permet de forma molt simple exposar ports, que quedaran oberts en la màquina Host com si fossin ports propis.

    Per tant, els ports que exposem quedaran disponibles (si no toquem res més) tant des-de localhost com des de la IP del nostre Host.

    De nou, utilitzarem un paràmetre alhora de crear un contenidor per esposar-ne un port, un conjunt de ports, o un rang. La forma de fer-ho és -p [IP_local:]<port_local>:<port_contenidor>[/protocol].

    Així doncs, i tornant a l'exemple d'un servei web, si volem exposar el port 80 del nostre contenidor com a port 80 del nostre host tan sols hem d'afegir alhora de crear el contenidor el següent paràmetre: -p 80:80.

    Si tinguéssim el port 80 local ja ocupat (per un altre servei) podríem triar un altre port sense problemes: -p 8080:80 d'aquesta manera tindríem el port local 8080 connectat al port 80 del contenidor.

    Un altre variació és establir l'adreça local on estarà aquest port disponible, això permetria per exemple obrir el servei tan sols per nosaltres -p localhost:80:80 o tan sols per una interfície específica -p 192.168.30.3:80:80.

    Un exemple de tot plegat:

    docker run --name srvTOR -d -p localhost:9050:9050 --restart=unless-stopped tor
    

    Es tracta d'un contenidor per al servei de TOR, aquí l'objectiu és tenir un port local on si hi redirigim el tràfic de qualsevol aplicació, aquest anirà per TOR i per tant serà anònim. Destacar el detall que aquest port 9050 tan sols estarà obert per localhost, es a dir la màquina pròpia, i no serà accessible per cap altre equip de la nostra xarxa.

  2. Assignació de IPs a contenidors

    Per poder assignar una IP concreta a un contenidor, hem de treballar primer amb una nova comanda de Docker que és l'encarregada de la gestió de xarxes: docker network. Les seves opcions son:

    Aquí bàsicament utilitzarem:

    create
    Per crear una nova xarxa de Docker.
    ls
    Per llistar les xarxes disponibles.
    rm
    per eliminar una xarxa.

    Per poder assignar una IP al nostre contenidor, primer haurem de crear una xarxa pròpia, per exemple la 192.168.1.0/24:

    docker network create --drive=bridge --subnet=192.168.1.0/24 --gateway=192.168.1.1 xarxa
    

    Un cop creada podrem crear un nou contenidor, en el exemple un servidor web Apache, amb la IP que vulguem assignar:

    docker container run -d -p 80:80 --name webIPfixa --network xarxa --ip 192.168.1.3 httpd
    

    Fixem-nos que els paràmetres que estem utilitzant per assignar la IP són dos:

    network
    Per connectar el contenidor a la xarxa abans creada.
    ip
    Per assignar una IP estàtica al contenidor.
  3. Assignar IPs "reals" a un contenidor

    Si volem assignar una IP del rang de la nostre xarxa real a un contenidor i que es comporti com un hostmés d'aquesta caldrà utilitzar el driver de xarxa anomenat macvlan.

    macvlan
    Aquest driver de xarxa assignarà una MAC a la interfície de xarxa fent que aparegui com un dispositiu físic dins la nostra xarxa.

    Tenint això, podem crear una xarxa que comparteixi un espai d'adreçament igual que la nostra xarxa real (on caldria tenir aquest espai reservat per Docke per evitar duplicats de IPs). I a partir d'aquí crear el contenidor amb aquesta nova xarxa i una IP fixa assignad a mà.

    docker network create --drive=macvlan --subnet=192.168.1.0/24 --gateway=192.168.1.1 xarxaREAL
    
    docker container run -d -p 80:80 --name srvWebIPFixa --network xarxaReal --ip 192.168.1.10 httpd
    

3.2.3. Receptes

Hem fet una visió ràpida de les eines que tenim per a utilitzar i combinar els nostres contenidors. Tanmateix alhora de crear-los i gestionar-los hi ha una quantitat de paràmetres ingent a poder utilitzar.

Per evitar que així és converteixi en un manual tècnic, veurem els cassos d'ús més típics i analitzarem els paràmetres emprats.

  1. Creació de contenidors

    Utilitzarem com a exemple a analitzar la creació i execució d'un contenidor per a donar server web, en aquest cas un Apache.

    docker run --name srvWEB -d -p 80:80 --network=xarxa --ip=192.168.1.3 -v /var/web/:/var/www/html/ --restart=unless-stopped httpd
    

    La major part dels paràmetres ja els hem vist a l'apartat de xarxes o volums, però apareixen alguns nous:

    –name
    Determinem un nom de contenidor, de manera que ens sigui més fàcil identificar-lo i referenciar-lo. Si no ho fem Docker n'assigna un aleatòriament.
    -d
    Detached el que fa és evitar que el contenidor passi a stopped en acabar la comanda que té assignada. Fixem-nos que en aquest cas llançar un apache serà quelcom com systemctl start apache2, si no afegim aquest paràmetre, en acabar d'executar la comanda anterior el contenidor es pararà.
    –restart=unsless-stopped
    Forcem que aquest contenidor sempre estigui funcionant, a menys que el parem de forma manual. Així si es reiniciar la màquina, peta el contenidor o qualsevol altre situació, Docker de forma automàtica tornarà a iniciar el contenidor.
  2. Entrar en contenidors

    Son poques les situacions en les que volem tenir accés a un contenidor ja que per a moltes (com mirar els logs) el propi Docker ja ens dona eines. Tanmateix les més típiques poden ser:

    • Volem "provar" un S.O. que hem muntat en docker, i per tant entrar-hi.
    • Volem accedir per fer alguna prova o inspeccionar quelcom molt concret.
    • Volem modificar el contenidor per a després crear una nova imatge a partir d'ell (poc recomanable).

    Per accedir a un contenidor tenim dues vies:

    Crear el contenidor i accedir-hi directament
    Podem fer-ho afegint a la comanda docker container run els paràmetres -it on -i és interactiu i -t terminal. Com podeu veure s'especifiquen junts amb -it, però poden anar per separats.
    Accedir a un contenidor ja que està funcionant
    Cal fer-ho amb la comanda docker container exec -it <contenidor> <comanda> normalment la comanda serà bash per obtenir una shell.

    dockerExecIT.gif

  3. Ús de variables

    Ens trobarem en molts contenidors que, donades les característiques del servei, en la seva instal·lació calgui definir alguns paràmetres, o simplement vulguem parametritzar quelcom. Casos típics poden ser un contenidor amb MySQL on, durant la instal·lació, cal especificar una contrasenya per accedir al servei com a root.

    Tenim dues opcions, que dependran molt de què vulguem parametritzar.

    Volem tocar arxius de configuració
    En casos com un contenidor amb DHCP o DNS voldrem modificar, i tenir ben guardats, els arxius de configuració. En aquest tipus de casos el més adient és utilitzar volums per "externalitzar" l'arxiu de configuració del contenidor i poder-lo gestionar des de la màquina host.
    Volem definir algun paràmetre concret del servei o de la instal·lació del mateix
    Podem utilitzar variables per parametritzar l'arrancada i construcció final de contenidor. Aquesta opció és molt còmode i recomanada, ja que tan sols permet "trastejar" paràmetres concrets que ens hagi deixat preparats el creador de l'imatge… però aquest ho ha hagut de tenir present i preparar-ho prèviament. Normalment trobarem informació sobre les variables que podem definir a la web de la pròpia imatge a Docker Hub o al Github del creador. Tot això és pot fer mitjançant el paràmetre -e <NOM_VARIALBE>=<VALOR> al fer un docker container run.
    docker container run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
    

    Aquest és un exemple de creació i execució d'un contenidor MySQL on podem veure que utilitzant -e MYSQL_ROOT_PASSWORD=my-secret se'ns permet establir la contrasenya de root per al servei MySQL en els últims passos de creació del contenidor.

  4. Execució de Apps GUI dins de Docker en host local

    Una forma d'executar aplicacions amb entorn gràfic des de dins de Docker és compartir les X11 del host amb el contenidor. Per això haurem de fer:

    xhost + #Permet que s'hi connectin altres equips a les nostres X11
    
    #Llançem el container compartint les X11 locals del host
    docker run -it --rm -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix:ro debian firefox
    

    La variable d'entorn DISPLAY també pot tenir la forma <IP>:display com per exemple 192.168.100.25:0.0.

4. TODO Creació d'imatges

4.1. Des d'un contenidor existent

4.2. Dockerfile

5. TODO Docker Compose

6. Docker Swarm

Docker Swarm és el component dins del grup d'eines de Docker per implementar un clúster d'equips físics que es coordinin entre ells per a servir un determinat nombre de contenidors.

Tot i ser una eina molt potent, s'ha vist superada per altres eines D'orquestració (que és com s'anomena la gestió de clústers de contenidors) com Kubernetes, que és una eina de Google Inc., ja que per un costat ofereixen major abstracció (interfície gràfica, etc) i la possibilitat de gestionar diferents tipus de contenidors i VMs (Docker, LXC, VirtualBox, VMWare, etc).

6.1. Característiques i conceptes de Docker Swarm

A part de la creació del clúster i la seva gestió integral, cal destacar que Docker Swarm també implementa de forma automàtica algunes característiques molt interessants.

Rol Manager
El node en crear el clúster obtindrà automàticament aquest rol, a posteriori en podem afegir més. Aquests seran els nodes que gestionaran el clúster i repartiran la feina. Cal notar que si cauen, el clúster deixa de funcionar.
Rol Worker
Són els nodes que aixequen els contenidors, sota les ordres dels Managers. És el rol per defecte dels nous nodes, i cal remarcar que un Manager també és per defecte Worker.
Balanceig de càrrega
Sempre que creem dos o més contenidors d'una mateixa imatge, Docker Swarm farà automàticament un balanceig de càrrega mitjançant Round Robin (enviarà cada petició nova al següent contenidor de la llista).
Service Discovery
Quan creem un contenidor dins del clúster, no tindrem en conte en quin node s'aixeca. Quan arribi una petició per aquest contenidor a qualsevol node del clúster, Docker Swarm aplicarà aquesta tècnica per esbrinar en quin node hi ha contenidors que responen a aquesta sol·licitud i la redirigirà automàticament cal a ells (aplicant el balanceig de càrrega).

6.2. Creació i gestió del clúster

Per crear un clúster de Docker Swarm necessitarem fer dos passos:

  1. Crear el clúster definint un node Manager.
  2. Afegir nous nodes Worker i/o Manager al clúster.

A part d'aquestes dues comandes o operacions, la resta d'operacions que aquí s'expliquen es poden realitzar des de qualsevol node del clúster, ja que ja és "un tot".

  1. Crear el primer node Manager

    Per crear el clúster lògicament necessitarem un equip amb GNU Linux i Docker instal·lat. Seguidament executem la comanda següent:

    docker swarm [--advertise-addr <ip>] init
    

    Paràmetres:

    –advertise-addr <ip>
    Opcional-ment podem afegir aquest paràmetre per especificar sobre quina interfície de xarxa treballarà el clúster. Tal com hem vist anteriorment pot ser interessant tenir interfícies de xarxa destinades a la gestió del clúster i altres a oferir els serveis.

    dockerswarminit.gif

  2. Afegir nous nodes Worker al clúster

    Un cop tenim el clúster creat, el propi resultat de la comanda docker swarm init ens ofereix la comanda per afegir nous nodes de tipus worker al clúster. Remarcar que la part important de la comanda és el TOKEN, que serà únic per aquest clúster (podríem tenir varis clústers, cadascú amb un token diferent). Per tant aquesta és la comanda a executar en el nou node.

    docker swarm join --token <TOKEN> <IP:PORT>
    

    Segons hem vist com a resultat de la comanda init anterior, la comanda per afegir un nou node al clúster sería:

    docker swarm join --token SWMTKN-1-53r2ov9r1knng7hyficwd8gwdqd266kh3m8s4e43b4usoppmn7-4cl3048dkxj7x55j8hfbtzakf 192.168.1.41:2377
    
  3. Sortir del clúster (des-promocionar un node)

    Ens pot interessar treure un node del clúster, per fer-ho caldrà executar:

    docker swarm leave [--force]
    
    –force
    Remarcar aquí que l'últim node viu d'un clúster, que forçosament serà un Manager, no es pot des-promocionar així, sinó que caldrà afegir el paràmetre --force per forçar-ho i eliminar definitivament el clúster.

    dockerswarmleave.gif

  4. Llistar nodes d'un clúster

    Per veure tots els nodes d'un clúster cal utilitzar la comanda:

    docker node ls
    

    dockernodels.gif

  5. Promocionar a Manager o degradar a Worker

    Les comandes son molt simples:

    docker node promote <id_node>
    docker node demote <id_node>
    

    On:

    promote
    Promocionem un Worker a Manager.
    modete
    Degradem o desproporcionem un Manager a Worker. Lògicament no ho podrem fer amb l'últim Manager.

    Aquí cal fer notar que molts cops, en clústers relativament petits i amb prou potència de hardware, el que es fa és promocionar tots els nodes a Manager, o una gran part. Això té l'inconvenient que tots els nodes tenen una feina extra, i es complica la coordinació, però es guanya en resiliència (ja no depenen d'un o dos Managers que si cauen el clúster deixa de funcionar). Per tant s'ha de "jugar" i trobar un equilibri que ens sigui profitòs.

  6. Activar, pausar i para nodes

    En el dia a dia de l'empresa podem necessitar canviar algun paràmetre d'un node. Per fer-ho tenim la comanda update:

    docker node update [--availability <active / pause / drain>] [opcions] <id_node>
    

    Aquí ja us indico l'opció més interessant –acailability que com el seu nom indica és l'estat del node. Ens pot interessar canviar-lo per fer proves, manteniment o operacions de maquinari sobre un node. Els estats que accepta són:

    active
    Funcionament normal.
    pause
    No accepta noves assignacions, però manté les actuals (els contenidors en funcionament).
    dain
    No accepta noves assignacions i cancel·la les actuals, és a dir, para tots els contenidors que tenia.

6.3. Gestió de serveis del clúster

Ens aquest apunts, per ara, ens centrarem en la creació i gestió de contenidors individuals dins del clúster. Tanmateix comentar que existeix Docker Stack que ve a ser un Docker Compose per a Docker Swarm.

  1. Creació de serveis dins Docker Swarm

    Per crear un nou servei o contenidor (fixeu-vos en el canvi de nomelatura) utilitzarem una comanda com la següent:

    docker service create [opcions] <imatge>[:tag]
    

    Per tant remarcar que totes les opcions que teníem amb la comanda docker container run les tenim també disponibles per docker service create. Tanmateix, i com és lògic i han algunes diferències, analitzem un exemple pràctic:

    docker service create --replicas 2 --name srvWEB -p 80:80 httpd:latest
    

    Podem veure els paràmetres nous:

    –replicas <#>
    Amb aquesta opció estem indicant que volem dos contenidors d'aquest tipus funcionant dins del clúster. Docker Swarm gestionarà de forma transparent i vetllarà per a que es compleixi sempre. Així si cau un node que contenia un d'aquests contenidors, automàticament n'aixecarà un de nou en un altre node del clúster.

    dockerservicecreate.gif

  2. Llistat de serveis

    Per llistar els serveis que s'estan executant al clúster utilitzarem la comanda:

    docker service ls
    

    dockerservicels.gif

  3. Escalar serveis

    Es pot donar el cas que detectem més demanda o menys d'un servei i necessitem adaptar el nombre de rèpliques d'un contenidor concret. Per fer-ho ho farem amb:

    docker service <nom_servei>=<#>
    

    Seguint l'exemple anterior podríem augmentar el nombre de servidors web així:

    docker service srvWEB=5
    
  4. Eliminar serveis

    Si volem eliminar un servei del clúster caldrà utilitzar aquesta comanda:

    docker service rm <nom_servei>
    

    Notar aquí que eliminarà tots els contenidors que associats al servei.

    Continuant amb l'exemple:

    docker service rm srvWEB
    

    dockerservicerm.gif

  5. TODO Docker Stack

7. TODO Activitats propossades

8. Bibliografía

9. Glossari

10. [1/6] 2Do

  • [ ] Recalcar en negreta els conceptes importants.
  • [X] Corrector.
  • [ ] Remarcar conceptes importants amb negreta.
  • [ ] Afegir entrades al glossari.
  • [ ] Afegir activitats.
  • [ ] Crear escenaris didàctics amb Katacoda.
  • [ ] Documentar nous drivers dexarxa macvlan i ipvaln.

11. Bitàcora

11.1. <2020-03-05 dj.>

Inicio el document de cara estructurar els continguts i que sigui més sencill explicar i aprendre Docker.

La part més complexa serà l'execució de contenidors donat el nombre d'opcions i possibles escenaris.

També caldrà veure si incidir en la redundància de dades, especialment en sistemes de cluster.

Finalment l'objectiu és fer-ne una introducció a Docker, i com a tal molts dels apartats son sobrers. S'hi afegeixen amb l'intenció de complementar la guia i donar material per aquells que tinguin ganes d'ampliar.

11.2. <2020-05-01 dv.>

Completació dels apunts "Introducció a la Virtualització" i "Primers passos amb Docker".

11.3. <2020-05-08 dv.>

El·laboració de l'apartat "Ús de Docker". Afegit l'apartat d'"Activitats propossades" on incloure enunciats i Katacoda per practicar. Enllaçar aquest apartats internament per saltar d'una secció a l'altre.

11.4. <2021-04-28 dc.>

Afegides tasques d'ampliació per canvis en drivers de xarxa.

Date: 2020-03-05 dj. 00:00

Author: Raul Gimenez Herrada

Created: 2023-11-15 dc. 08:59