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:
Això crea un volum anomenat "dades-mysql". Podeu veure tots els vostres volums amb:
Per obtenir informació detallada sobre un volum:
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:
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:
Atenció: només podeu eliminar un volum si cap contenidor l'està utilitzant actualment. Si heu d'eliminar contenidors i els seus volums alhora:
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:
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:
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:
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:
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:
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.