====== Docker pràctic ====== Docker és una tecnologia de gestió de //containers//. Els contenidors són un entorn aïllat d'execució segur, a mode de màquina virtual lleugera, i que s'executen aprofitant el mateix nucli de la màquina //host//. {{ docker-logo-1.png?direct&300 }} Articles relacionats: * Anterior: [[docker_pres]] * Següent: [[docker-compose]] Altres articles sobre Docker a aquesta wiki: {{topic> docker}} {{tag> #FpInfor #Ciber #CiberMp03 #Ceti #CetiMp03 #Asix #AsixMp08 DevOps docker containers contenidors }} ===== Instal·lació ===== Es recomana treballar sobre Ubuntu, és més fàcil en general. En Ubuntu Linux podem instal·lar fàcilment la versió que hi ha als repositoris: $ sudo apt update $ sudo apt install docker.io Pots crear una VM Ubuntu amb [[Vagrant]] fàcilment amb: $ mkdir ubudocker $ cd ubudocker $ vagrant init ubuntu/jammy64 Edita el ''Vagrantfile'' i activa la xarxa externa per fer-lo accessible per xarxa. Descomenta la línia: config.vm.network "public_network" Posa en marxa la VM: $ vagrant up $ vagrant ssh Podem treballar com si fos un Ubuntu si instal·lem el WSL (Windows Subsystem for Linux). Obriu un CMD amb permisos d'administrador i excecuteu: > wsl --install Quan finalitzi la instal·lació cal fer un reinici i, per defecte, tindràs una Ubuntu Linux instal·lada en el sistema. Cerca l'aplicació "Ubuntu" i se t'obrirà una //shell// de Linux. Pots treballar com amb la versió Ubuntu. **Consulta la pestanya d'Ubuntu per fer la instal·lació**. Només amb una diferència: per poder executar el //dockerd// caldrà que obris una //shell// de Ubuntu a part i executis: $ sudo dockerd Obre una altra //shell// Ubuntu per llençar les comandes, com per exemple: $ docker ps A les versions GNU/Linux, per no haver de fer ''sudo'' per les comandes ''docker'' afegim el nostre usuari al grup ''docker'': $ sudo adduser myuser docker I també afegim l'eina Byobu per a millora de la shell que ens serà pràctic: $ sudo apt install byobu $ byobu-enable Caldrà sortir i entrar a la sessió gràfica o a la //shell// perquè el canvi de grup ''docker'' prengui efecte. \\ ===== Exemples pràctics: search i pull ===== ''docker search'' per buscar imatges al Docker Hub (https://hub.docker.com) $ docker search ubuntu ''docker pull'' per descarregar una imatge: $ docker pull ubuntu:focal $ docker pull centos:8 El format ''imatge:tag'' ens permet descarregar diverses versions del mateix contenidor. \\ ===== Exemples pràctics: images ===== ''docker images'' per veure les imatges que hem descarregat $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu focal 597ce1600cf4 4 days ago 72.8MB debian latest a178460bae57 7 days ago 124MB centos latest 5d0da3dc9764 2 weeks ago 231MB ubuntu groovy e508bd6d694e 2 months ago 79.4MB \\ ===== Primeres passes ===== Exemple d'arrencada d'un contenidor ''hello-world'' que ens descarregarà i posarà en marxa un docker que imprimirà un missatge de "hello world" i sortirà: $ docker run hello-world Fixeu-vos en què tornem a tenir disponible la //shell// mentre que aquest altre exemple la bloqueja: $ docker run httpd Podem obrir una altra //shell// de ''byobu''amb F2. Els shorcuts son: * F2 : obre una //shell// nova. * F3 i F4 : moure'ns entre les diferents //shells//. * F6 : sortir mantenint la configuració de les diferents //shells// remotes. Ara podràs comprovar que el docker httpd està funcionant amb **''docker ps''**: vagrant@ubuntu-focal:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1cf40af37371 httpd "httpd-foreground" 4 minutes ago Up 4 minutes 80/tcp heuristic_curran Amb **''docker ps -a''** també veurem el docker inicial creat: vagrant@ubuntu-focal:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES af672fa8016d hello-world "/hello" 7 seconds ago Exited (0) 6 seconds ago jolly_ellis 1cf40af37371 httpd "httpd-foreground" 5 minutes ago Up 5 minutes 80/tcp heuristic_curran Fixa't que Docker anomena els contenidors amb nom i cognom aleatoris. Veiem que ''hello-world'' està parat. El podem intentar reviure amb ''docker start'' però veurem que torna a sortir sense fer res mes. Encara que tècnicament no és "mort", el podem donar com a tal, perquè ha realitzat la seva funció (imprimir un missatge) i ha acabat la seva feina (exited). {{ docker-container-lifecycle.png?direct&500 }} Si el volem eliminar del tot perquè no ocupi espai de disc, podem fer (amb les 3 primeres xifres del ID n'hi ha prou, i també funciona amb el nom): $ docker rm Ara, al fer ''docker ps -a'' ja no ens sortirà. \\ ===== Accedint al contenidor per xarxa interna ===== Intentarem veure si el ''httpd'' sí que està actiu. Per començar, mirarem quina és la seva adreça IP interna: $ docker inspect | grep -i ipadd "SecondaryIPAddresses": null, "IPAddress": "172.17.0.2", "IPAddress": "172.17.0.2", Ara podem intentar contactar-lo i veure si ens mostra una web (httpd és l'Apache): $ curl 172.17.0.2

It works!

Veiem que sí que funciona i hi podem accedir i veure el contingut. El problema és que només es pot accedir per la màquina //host// del Docker Daemon. \\ ===== Publicar ports ===== Per publicar un port ho hem de fer en el moment de creació del contenidor. Ara crearem un docker nou amb les següents característiques: * Nom personalitzat "amadeus". * En mode //daemon// perquè no ens bloquegi la //shell//. * Publicant el port 80 (http) sobre el port 8000 de la màquina //host//. $ docker run --name amadeus -d -p 8000:80 httpd {{ docker5.png?direct&450 }} Com abans, podríem accedir a la web per la IP interna, però el què ens interessa és que aquest port es publiqui a la màquina //host// i que sigui abastable externament. Així, podem accedir amb: $ curl localhost:8000 Per accedir amb el navegador, primer caldrà que coneixem la IP de la VM, fent $ ip add | grep inet I ara podem accedir via //browser// http://:8000 \\ ===== Entrar a un contenidor ===== Per accedir dins un contenidor podem executar una //shell//. Cal distingir entre les opcions: * docker run : posa en marxa un nou contenidor * docker exec : executa una instrucció en un contenidor existent Pel nostre cas, farem (-ti és per emular un terminal i enganxar-nos): $ docker exec -ti amadeus bash Podem comprovar quina distribució base de Linux fa servir, fent: $ cat /etc/os-release ==== Exercici 1 ==== Entra al contenidor amadeus, modifica el contingut del HTML (index.html), i comprova que a la web es veuen els canvis. \\ ===== Esborrar tots els containers aturats ===== Molt sovint cal fer neteja de tots els container aturats. Es pot fer de diverses maneres, però la més còmoda és: $ docker rm $(docker ps -aq) La flag -a ens mostra tots els contenidors i -q ens treu només els seus IDs. Els containers en estat ''running'' no es poden matar, ja que primer cal que estiguin aturats. \\ ===== Connectant als serveis del contenidor ===== Mirarem ara de connectar a un docker de MariaDB a través d'un client estàndard (no mitjançant eines de Docker). ==== Exercici 2 ==== * Llegeix la documentació del Docker oficial de MariaDB al Docker Hub: * https://hub.docker.com/_/mariadb * Posa en marxa un Docker de MariaDB i publica el port 3306 intern al 33006 extern (màquina host). * ''docker run ... -p 33006:3306 mariadb:latest'' * Instal·la el **client** de MariaDB a la màquina //host// i connecta't via CLI a través del port local 33006: * ''mysql -u myuser -pmypass -h 127.0.0.1 -P 33006'' * Crea una BD i una taula a dins amb algun registre. * Surt del CLI de Mariadb. * Para el docker (stop). Comprova que ara no hi pots accedir. * Posa en marxa (start) el docker de nou. * Connecta't i comprova que tornes a connectar-te i que les dades hi són. * Destrueix el contenidor (''docker stop'' + ''docker rm'' o bé ''docker rm -f'') * Torna'l a crear i comprova que la BD ja no existeix. Com podrem comprovar, els continguts del Docker son efímers, al destruir el contenidor, també es destrueix el seu espai de disc dur. \\ ===== Volumes ===== Els docker volumes ens permeten persistir el contingut que d'altra manera seria efímer. Tenim 2 maneres de persistir l'espai de disc dur: * **Bind mounts**: triem l'espai del //filesystem// on volem guardar les dades. * **Volumes**: etiquetem el volum que volem utilitzar i el deixem que Docker el guardi al seu espai privat (normalment ''/var/lib/docker/volumes''). {{ docker-volumes.png?direct&400 }} Per exemple, per persistir la BD de dades mitjançant un //bind mount// ho farem mitjançant ''-v /path/to/data:/docker/path'': $ docker run --name maria1 -v ~/mysql1:/var/lib/mysql -e MARIADB_ROOT_PASSWORD=my-secret-pw -d mariadb Si enlloc d'un //bind mount// volem un //**volume**//, ho farem canviant -v amb una simple etiqueta (en aquest cas, ''mysql2''): $ docker run --name maria2 -v mysql2:/var/lib/mysql -e MARIADB_ROOT_PASSWORD=my-secret-pw -d mariadb Comprova que el nou volum s'ha creat fent: $ sudo ls -la /var/lib/docker/volumes ==== Exercici 3 ==== Comprova la persistència dels volums repetint l'exercici 2 i veient que al recrear el Docker les dades (DB) es mantenen. \\ ===== Xarxes Docker ===== El més habitual és fer compartiments estancs amb xarxes BRIDGE. Quan creem una xarxa //bridge//, les màquines en aquesta es veuen entre sí i es reconeixen per nom, no només per la IP. Docker Engine els fa de DNS. La xarxa ''default'' és una excepció: les màquines es veuen entre sí, però no tenen "autodiscover" per nom. Per a fer que es coneguin les màquines per nom a la xarxa ''default'' podem utilitzar el flag ''--link'', que està obsolet però que encara té aquesta utilitat. {{ docker-network.png?direct&550 }} $ docker network create net1 $ docker run --name www1 --net net1 -d httpd \\ ===== Continuació ===== El tema Docker continua a [[docker-compose]]. \\ ===== Alternatives a Docker ===== Podeu veure l'article sobre [[Podman]]. \\