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).
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.
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
orun
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.
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: 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.
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.
- 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.
- 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.
- 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.
- 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.
- 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.
- Ú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 undocker 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. - 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:
- Crear el clúster definint un node Manager.
- 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".
- 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.
- 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
- 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.
- Llistar nodes d'un clúster
Per veure tots els nodes d'un clúster cal utilitzar la comanda:
docker node ls
- 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.
- 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.
- 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 perdocker 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.
- Llistat de serveis
Per llistar els serveis que s'estan executant al clúster utilitzarem la comanda:
docker service ls
- 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
- 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
- TODO Docker Stack
7. TODO Activitats propossades
8. Bibliografía
- Docker: Documentació oficial de Docker.
- Docker: SecDevOps: Llibre de seguretat en Docker de l'editorial 0xWord.
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 dexarxamacvlan
iipvaln
.
11. Bitàcora
11.1.
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.
Completació dels apunts "Introducció a la Virtualització" i "Primers passos amb Docker".
11.3.
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.
Afegides tasques d'ampliació per canvis en drivers de xarxa.