Salta el contingut

Volums i Xarxes a Docker

Gestionant dades: volums i persistència

Un dels aspectes més importants (i sovint més confusos) de Docker és com gestionar les dades. Recordeu que els contenidors són efímers per disseny: quan elimineu un contenidor, tot el que hi havia dins desapareix. Però moltes aplicacions necessiten emmagatzemar dades de forma persistent: bases de dades, fitxers pujats pels usuaris, logs, etc. Aquí és on entren els volums.

Per què necessitem volums

Imagineu que executeu una base de dades MySQL dins d'un contenidor. Els usuaris afegeixen dades, i tot funciona perfectament. Però després decidiu actualitzar MySQL a una versió més nova. Per fer-ho, elimineu el contenidor vell i en creeu un de nou amb la nova versió. De cop i volta, totes les dades han desaparegut! Això no és acceptable.

La solució són els volums. Un volum és una manera d'emmagatzemar dades fora del sistema de fitxers del contenidor, en una ubicació gestionada per Docker al sistema amfitrió. Quan elimineu el contenidor, el volum i les seves dades es mantenen. Quan creeu un nou contenidor, podeu muntar el mateix volum i les dades estaran allà.

Tipus de muntatges: volums, bind mounts i tmpfs

Docker ofereix tres maneres principals de muntar dades en un contenidor, i és important entendre les diferències:

Els volums són l'opció recomanada per Docker. Són completament gestionats per Docker i s'emmagatzemen en una part específica del sistema de fitxers de l'amfitrió (normalment dins de /var/lib/docker/volumes/ en Linux). No heu de preocupar-vos de rutes absolutes o permisos complicats. Docker s'encarrega de tot. Els volums també funcionen millor amb Docker Desktop en Windows i Mac.

Els bind mounts munten un directori o fitxer específic del vostre sistema amfitrió dins del contenidor. Això és útil durant el desenvolupament perquè podeu editar els fitxers al vostre ordinador amb el vostre editor favorit, i els canvis es reflecteixen immediatament dins del contenidor. La desavantatge és que sou responsables de gestionar els permisos i les rutes.

Els tmpfs mounts són volums que s'emmagatzemen a la memòria RAM, no al disc. Són útils per dades temporals que no necessiten persistir i que voleu que siguin molt ràpides.

Treballant amb volums

Anem a veure exemples pràctics. Primer, crearem un volum:

docker volume create dades-mysql

Això crea un volum anomenat "dades-mysql". Podeu veure tots els vostres volums amb:

docker volume ls

Per obtenir informació detallada sobre un volum:

docker volume inspect dades-mysql

Això us mostrarà on s'emmagatzema físicament el volum al vostre sistema.

Ara anem a utilitzar aquest volum amb una base de dades MySQL:

docker run -d \
  --name mysql-db \
  -e MYSQL_ROOT_PASSWORD=contrasenya_segura \
  -v dades-mysql:/var/lib/mysql \
  mysql:8.4

Analitzem aquesta comanda. El paràmetre -e estableix una variable d'entorn dins del contenidor. MySQL necessita que li especifiqueu la contrasenya de root mitjançant aquesta variable. El paràmetre -v dades-mysql:/var/lib/mysql és el més important: munta el volum "dades-mysql" al directori /var/lib/mysql dins del contenidor, que és on MySQL emmagatzema totes les seves dades.

Ara, si elimineu aquest contenidor i en creeu un de nou muntant el mateix volum, totes les dades estaran allà. Això és essencial per a bases de dades i qualsevol altre servei que necessiti persistència.

Utilitzant bind mounts per desenvolupament

Durant el desenvolupament, sovint és útil utilitzar bind mounts perquè podeu editar el codi al vostre ordinador i veure els canvis immediatament sense haver de reconstruir la imatge. Per exemple, amb la nostra aplicació Flask d'abans:

docker run -d \
  -p 5000:5000 \
  -v $(pwd):/app \
  --name app-dev \
  la-meva-app:1.0

El $(pwd) (o ${PWD} en PowerShell) s'expandeix al directori actual. Això munta el vostre directori de treball dins de /app al contenidor. Ara, si editeu app.py al vostre ordinador, els canvis es veuran dins del contenidor. Depenent de com estigui configurada l'aplicació, pot ser que hagueu de reiniciar el contenidor per veure els canvis, però no cal reconstruir la imatge.

Netejant volums

Els volums ocupen espai al disc, així que de tant en tant haureu de netejar els que ja no utilitzeu. Per eliminar un volum:

docker volume rm dades-mysql

Atenció: només podeu eliminar un volum si cap contenidor l'està utilitzant actualment. Si heu d'eliminar contenidors i els seus volums alhora:

docker rm -v nom-del-contenidor

L'opció -v elimina els volums anònims associats amb el contenidor.

Per eliminar tots els volums que no estan sent utilitzats per cap contenidor:

docker volume prune

Aquesta comanda us demanarà confirmació abans d'eliminar res, per seguretat.

Xarxes a Docker: comunicació entre contenidors

Un aspecte fonamental de Docker que sovint es passa per alt és com funciona la xarxa. Quan executeu múltiples contenidors que necessiten comunicar-se entre ells, Docker proporciona diverses opcions de xarxa que us permeten controlar com es comuniquen.

Com funcionen les xarxes Docker per defecte

Quan instal·leu Docker, crea automàticament tres xarxes: bridge, host, i none. Podeu veure-les executant:

docker network ls

La xarxa "bridge" és la xarxa per defecte. Quan executeu un contenidor sense especificar una xarxa, Docker el connecta automàticament a aquesta xarxa bridge. Els contenidors en aquesta xarxa poden comunicar-se entre ells usant les seves adreces IP, però NO poden comunicar-se usant els seus noms. Això és important: si teniu dos contenidors a la xarxa bridge per defecte, no podeu fer ping nom-contenidor, heu d'usar l'adreça IP.

La xarxa "host" elimina l'aïllament de xarxa entre el contenidor i el sistema amfitrió. Si un contenidor està connectat a la xarxa host, utilitzarà directament la xarxa de l'amfitrió, sense cap mapatge de ports. Això pot ser útil per aplicacions que necessiten molt rendiment de xarxa, però elimina part de l'aïllament que proporcionen els contenidors.

La xarxa "none" desactiva completament la xarxa per al contenidor. És útil per contenidors que no necessiten connectivitat de xarxa en absolut.

Creant xarxes personalitzades

La pràctica recomanada és crear xarxes personalitzades per les vostres aplicacions. Els contenidors en xarxes personalitzades poden comunicar-se entre ells usant els seus noms com a hostnames, cosa que fa la configuració molt més senzilla. A més, proporcionen millor aïllament: només els contenidors que explícitament connecteu a una xarxa poden comunicar-se amb els altres contenidors d'aquesta xarxa.

Per crear una xarxa:

docker network create la-meva-xarxa

Ara podeu executar contenidors connectats a aquesta xarxa:

docker run -d --name contenidor1 --network la-meva-xarxa nginx
docker run -d --name contenidor2 --network la-meva-xarxa nginx

Des de contenidor1, podríeu fer ping contenidor2 i funcionaria! Docker proporciona resolució DNS automàtica dins de xarxes personalitzades.

Si teniu un contenidor que ja està en execució i voleu connectar-lo a una xarxa addicional:

docker network connect la-meva-xarxa nom-contenidor

Un contenidor pot estar connectat a múltiples xarxes simultàniament.

Exemple pràctic: aplicació web amb base de dades

Anem a veure un exemple pràctic de com utilitzar xarxes. Crearem una xarxa per una aplicació web i la seva base de dades:

docker network create xarxa-app

docker run -d \
  --name mysql-backend \
  --network xarxa-app \
  -e MYSQL_ROOT_PASSWORD=contrasenya \
  -e MYSQL_DATABASE=app_db \
  mysql:8.4

docker run -d \
  --name web-frontend \
  --network xarxa-app \
  -p 8080:80 \
  nginx

Ara el contenidor "web-frontend" pot accedir a "mysql-backend" simplement usant el nom "mysql-backend" com a hostname. En el fitxer de configuració de l'aplicació, podríeu posar:

DB_HOST=mysql-backend
DB_PORT=3306

I funcionaria perfectament. No cal especificar adreces IP que poden canviar, no cal configurar cap mapatge de ports (els contenidors dins de la mateixa xarxa poden parlar entre ells directament pels ports interns).

Docker Compose fa tot això automàticament: crea una xarxa per defecte per cada projecte i hi connecta tots els serveis, permetent que es comuniquin per nom.

Seguretat i aïllament

Les xarxes també proporcionen seguretat. Si teniu múltiples aplicacions diferents al mateix servidor, podeu posar cada aplicació en la seva pròpia xarxa. Els contenidors d'una aplicació no podran accedir als contenidors d'altres aplicacions, proporcionant aïllament.

Per exemple, podríeu tenir: - Xarxa "app1" amb el frontend, backend i base de dades de l'Aplicació 1 - Xarxa "app2" amb el frontend, backend i base de dades de l'Aplicació 2

Els contenidors de l'Aplicació 1 no podran accedir als de l'Aplicació 2, i viceversa.