Salta el contingut

0614 - Bloc 3: Desplegament d'aplicacions web

Bloc 3: Desplegament amb Docker

Docker és una plataforma de codi obert dissenyada per facilitar la creació, implementació i execució d'aplicacions en contenidors.

Un contenidor es pot definir com un entorn lleuger, aïllat i portàtil, que inclou tot el necessari (codi font, dependències, configuracions, etc.) per executar una aplicació de manera independent.

Normalment, un contenidor executa un únic procés, tot i que és possible executar-ne diversos si cal.

Una de les grans avantatges de l'ús de contenidors és que garanteixen que una aplicació es pugui executar de la mateixa manera en qualsevol entorn, des de l'ordinador de desenvolupament fins a un servidor de producció. Això redueix els problemes relacionats amb les diferències entre entorns i facilita la col·laboració entre equips de desenvolupament i operacions.

Contenidors vs màquines virtuals

Els contenidors i les màquines virtuals (VMs) són dues tecnologies diferents que s'utilitzen per aïllar aplicacions i serveis, però tenen diferències significatives en la seva arquitectura i funcionament.

Maquines virtuals vs docker

Stack de la Contenerització

Estructura de capes del sistema Docker:

  1. Aplicació
    Codi font + dependències (p. ex. Node.js, PHP, Python).
  2. Contenidor
    Aïllament de processos i recursos.
  3. Docker Engine
    Motor que crea i gestiona els contenidors.
  4. Sistema Operatiu (Host OS)
    Normalment Linux (encara que pot ser Windows o macOS amb adaptació).
  5. Maquinari físic o virtual
    CPU, memòria, emmagatzematge, xarxa.
Categoria Exemples
Plataforma OpenShift, Docker Enterprise Edition, Rancher, DC/OS
Orquestrador Kubernetes, Docker Swarm, Mesos
Motor de contenidorització Docker, Podman, rkt, LXD, cri-o
Sistema Operatiu Windows, Linux, macOS

Tecnologies de Contenerització

Abans de Docker existien altres tecnologies similars:

Tecnologia Desenvolupador Any Característiques
LXC (Linux Containers) Canonical 2008 Contenidors basats en kernel Linux
rkt (Rocket) CoreOS 2014 Enfoc en seguretat i estàndards
Podman Red Hat 2018 Sense dimoni central, més segur
Docker Docker Inc. 2013 API senzilla i ecosistema complet

Docker es va imposar per la seva facilitat d’ús i ecosistema ampli (Docker Hub, Docker Compose, Docker Swarm, etc.).

Orquestradors i Plataformes

Quan una aplicació té molts contenidors, cal una eina que els gestioni i coordini.

Orquestradors principals:

  • Docker Swarm: orquestrador natiu de Docker.
  • Kubernetes: l’orquestrador més utilitzat (Google).
  • OpenShift, Nomad: altres opcions industrials.

Plataformes basades en Docker:

  • AWS ECS (Elastic Container Service)
  • Google Cloud Run / GKE
  • Azure Container Apps

Conceptes bàsics de Docker

La imatge més descriptiva sol ser la següent:

Docker Workflow A continuació es presenten els conceptes bàsics que cal entendre:

  • Contenidor:

  • Un contenidor és una instància en execució d'una imatge que pot contenir un o més processos en funcionament. Per crear un contenidor, només cal iniciar una imatge amb la comanda docker run.

  • Es tracta d'un procés que s'executa en un entorn aïllat. Els contenidors comparteixen el nucli del sistema operatiu de l'amfitrió, però estan aïllats entre si i de l'amfitrió. Això els fa lleugers i eficients en termes de recursos, ja que no necessiten un sistema operatiu complet per a cada instància.

  • Imatge:

  • És un fitxer binari que conté tots els elements necessaris per executar un contenidor. Podria considerar-se com una plantilla utilitzada per crear contenidors.

  • Podem dir que les imatges de Docker són una instantània d'un contenidor i que els contenidors es creen a partir d'una imatge.

  • Dockerfile:

  • És un fitxer de configuració escrit en text pla, que conté totes les instruccions necessàries per crear una imatge Docker. Aquest fitxer defineix el sistema operatiu base, les aplicacions i les dependències que s'han d'incloure a la imatge, així com les configuracions específiques que cal aplicar.

  • Docker Engine:

  • És el motor de Docker que s'encarrega de crear, executar i gestionar els contenidors. És una aplicació de servidor que s'executa en segon pla i que proporciona una interfície per interactuar amb Docker mitjançant la línia d'ordres o l'API REST.

  • Docker Registry:

  • És un repositori d'imatges de contenidors. És similar a un GitHub, però per a imatges de contenidors.

  • Docker Hub és el registre oficial on estan allotjats els repositoris de les imatges Docker que podem utilitzar en els nostres contenidors. A Docker Hub poden existir imatges públiques i privades, així com imatges oficials i altres creades per desenvolupadors independents.

    Per realitzar la cerca d'imatges, podem fer-ho des de la web oficial:

    https://hub.docker.com

    També podem fer-ho des de la consola amb la comanda docker search. Per exemple, per cercar totes les imatges que continguin la paraula ubuntu, utilitzem la comanda:

    docker search ubuntu
    

Resum dels Conceptes Clau

Term Descripció breu
Contenidor Entorn lleuger i aïllat que executa una aplicació.
Imatge Plantilla (read-only) per crear contenidors.
Docker Engine Component que gestiona les imatges i contenidors.
Registry Repositori d’imatges (p. ex. Docker Hub).
Orquestrador Gestor de múltiples contenidors en xarxa.

Arquitectura de Docker

Docker segueix una arquitectura client-servidor composta per diversos elements que treballen conjuntament.

Components principals

Component Descripció
Docker Client (CLI) Interfície de línia d’ordres. Envia instruccions al servidor.
Docker Daemon (dockerd) Servei que executa i gestiona contenidors i imatges. Escolta peticions del client.
Docker Engine Conjunt format pel Client + Daemon + API REST.
Docker API REST Permet a aplicacions externes comunicar-se amb el daemon.
Imatges Plantilles de només lectura que contenen el sistema i les dependències.
Contenidors Instàncies d’imatges que s’executen.
Volums Sistemes de fitxers persistents.
Xarxes (Networks) Permeten la comunicació entre contenidors.
Registry (Docker Hub) Repositori per emmagatzemar i compartir imatges.

Fonaments Docker

Primer contacte amb Docker

Un cop instal·lat, podem començar amb ordres bàsiques per verificar que tot funciona correctament.

Comprovar la instal·lació

docker version
docker info

Aquesta comanda ens permet cercar imatges a Docker Hub.

Exemple:

Per exemple, per cercar totes les imatges que continguin la paraula ubuntu, utilitzem la comanda següent:

docker search ubuntu

El resultat podria ser semblant al següent:

NAME                                                   DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
ubuntu                                                 Ubuntu és un sistema operatiu basat en Debian…   8763                [OK]
dorowu/ubuntu-desktop-lxde-vnc                         Ubuntu amb openssh-server i NoVNC               242                                     [OK]
...

Descàrrega d’una imatge (docker pull)

Aquesta comanda ens permet descarregar una imatge des de Docker Hub.

Exemple 1:

Per exemple, per descarregar la imatge ubuntu, executaríem la següent comanda:

docker pull ubuntu

Exemple 2:

Per descarregar la imatge wordpress, faríem el següent:

docker pull wordpress

Docker Imatges

  • Una imatge és una plantilla immutable que defineix el contingut d’un contenidor.
  • Conté: sistema base (p. ex. Ubuntu, Alpine), llibreries i aplicacions.
docker images

Mostra un llistat amb totes les imatges locals disponibles.

Exemple:

Per veure el llistat de les imatges que tenim descarregades al nostre equip, executaríem la següent comanda:

docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
httpd               latest              fcf3e41b8864        fa 2 setmanes         40MB
ubuntu              latest              2d696327ab2e        fa 2 mesos           122MB

Exemple:

El modificador -q ens permet mostrar només l'identificador de la imatge en el llistat de sortida. Aquesta opció ens serà útil quan vulguem eliminar totes les imatges de forma massiva.

docker images -q
fcf3e41b8864
2d696327ab2e

Eliminar imatges (docker rmi)

Aquesta comanda ens permet eliminar una o diverses imatges.

Exemple 1:

Per eliminar la imatge wordpress, utilitzem la següent comanda:

docker rmi ubuntu

Exemple 2:

Per eliminar totes les imatges que tenim de manera local, podem utilitzar la comanda següent:

docker rmi $(docker images -q)

Aquesta comanda utilitza la sortida de docker images -q per obtenir tots els identificadors de les imatges locals i les elimina de manera massiva.

Cicle de vida d’un contenidor Docker

  1. Crear: docker create <nom_imatge>
  2. Arrancar: docker start <nom_contenidor>
  3. crear i arrencar: docker run <nom_imatge>
  4. Aturar: docker stop <nom_contenidor>
  5. Eliminar: docker rm <nom_contenidor>
  6. pausar: docker pause <nom_contenidor>
  7. Continuar: docker unpause <nom_contenidor>
  8. Reiniciar: docker restart <nom_contenidor>

Cicle de vida d'un contenidor Docker

Arrancar un contenidor Docker

Per arrencar un contenidor Docker, utilitzem la comanda docker run seguida del nom de la imatge que volem executar.

Exemple:

docker run httpd

Aquest comandament:

  1. Cerca la imatge httpd localment.
  2. Si no existeix, la descarrega del Docker Hub.
  3. Executa el contenidor i mostra un missatge de confirmació.
  4. Bloqueja la terminal en primer pla fins que s'aturi el contenidor.

Sortida esperada:

Arranca un contenidor amb el servidor HTTP Apache. Bloquejant la terminal en primer pla. Per apagar-lo, prem Ctrl+C.
Per accedir al servidor, obre un navegador i visita http://localhost:80 (hem de mapejar el port 80 del contenidor al port 80 de l'amfitrió).

Aquesta comanda de docker run ... és molt potent i té moltes opcions per personalitzar el comportament del contenidor.

Alternativament hi ha dues maneres de crear un contenidor a Docker:

  • docker run -it: Crea contenidors en mode interactiu que s’executen en primer pla i ens permeten interactuar amb ells mitjançant la terminal de l’entrada estàndard (STDIN).
  • docker run -d: Crea contenidors en mode detached, que s’executen en segon pla.

Opcions comunes de docker run Juntament amb la comanda docker run, podem utilitzar una sèrie d’opcions per personalitzar el comportament del contenidor. Algunes de les opcions més habituals són:

  • -d: Inicia el contenidor en segon pla.
  • -i: Manté oberta l’entrada estàndard (STDIN) del contenidor, permetent interacció amb ell.
  • -t: Assigna un terminal TTY al contenidor, cosa que fa que la sortida sigui llegible i interactiva.
  • -p: Mapeja un port del contenidor a un port de l’amfitrió.
  • -v: Mapeja un volum de l’amfitrió al contenidor.
  • --name: Assigna un nom al contenidor.
  • --rm: Elimina el contenidor en aturar-lo.
  • -e: Defineix una variable d’entorn.
  • --env-file: Defineix un fitxer amb variables d’entorn.

A continuació, veurem diversos exemples per entendre com funcionen aquestes opcions:

Exemple 1: Iniciar un contenidor en mode interactiu

docker run -it --name alpine-container --rm alpine

docker run és la comanda que ens permet crear un contenidor a partir d’una imatge Docker.

  • El paràmetre -i ens permet interactuar amb el contenidor mitjançant l’entrada estàndard (STDIN).
  • El paràmetre -t assigna un terminal dins del contenidor.
  • Els paràmetres -it combinats ens permeten utilitzar un contenidor com si fos una màquina virtual tradicional.
  • El paràmetre --name ens permet assignar un nom al contenidor. Si no li assignem un nom, Docker en crearà un automàticament.
  • El paràmetre --rm fa que, quan sortim del contenidor, aquest s’elimini automàticament i no ocupi espai al disc.

alpine és el nom de la imatge. Si no s’indica el contrari, Docker buscarà la imatge al repositori oficial Docker Hub.

Un cop executada la comanda anterior, apareixerà un terminal del contenidor que acabem de crear:

/ #

Si volguéssim instal·lar nano dins del contenidor, hauríem de fer el següent:

  1. Actualitzar l’índex de paquets disponibles:
apk update
  1. Afegir el nou paquet al sistema:
apk add nano

Per sortir del contenidor, escrivim el comandament:

exit

Com que hem iniciat el contenidor amb el paràmetre --rm, en sortir del contenidor aquest s’elimina automàticament i no ocupa espai al disc. Podem comprovar-ho amb la comanda:

docker ps -a

Exemple2 : Iniciar un contenidor en mode detached amb mapeig de ports

docker run -d --name webserver --rm -p 80:80 nginx
  • El paràmetre -d indica que volem executar el contenidor en segon pla (background).
  • El paràmetre --name ens permet assignar un nom al contenidor (webserver).
  • El paràmetre --rm fa que el contenidor s’elimini automàticament quan es detingui.
  • El paràmetre -p mapeja el port 80 del nostre equip al port 80 del contenidor, permetent accedir al servei des de l’exterior.

Contenidor nginx amb mapeig de ports

Exemple:

docker run -d --name webserver --rm -p 80:80 -v /home/jordi/web:/usr/share/nginx/html nginx
  • El paràmetre -v ens permet crear un volum per mapar un directori del nostre equip amb el directori que Nginx utilitza per servir les pàgines web.

També podem utilitzar $(pwd) per indicar que volem crear un volum en el directori actual:

docker run -d --name webserver --rm -p 80:80 -v $(pwd):/usr/share/nginx/html nginx

Això ens permet treballar amb els fitxers del projecte directament des del directori on estem, sense haver de copiar-los dins del contenidor.

Contenidor nginx amb mapeig de ports i binding de volums

Mostrar els contenidors docker

Per mostrar els contenidors, utilitzem la comanda:

docker ps

Aquesta comanda mostra només els contenidors en execució.

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

Per veure tots els contenidors, inclosos els aturats, utilitzem el modificador -a:

docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS               NAMES
cfc8008e704b        ubuntu              "/bin/echo 'Hello ..."   7 seconds ago       Exited (0) 5 seconds ago                        boring_almeida

Política de reinici

Per defecte, quan un contenidor falla o finalitza el seu procés, Docker no el reinicia automàticament. Si volem que un contenidor es reiniciï de manera automàtica, podem utilitzar l’opció --restart. Aquesta opció ens permet definir una política de reinici. Algunes de les polítiques més habituals són:

  • no: No reinicia el contenidor.
  • always: Reinicia el contenidor sempre.
  • unless-stopped: Reinicia el contenidor sempre que no l’aturis manualment.
  • on-failure: Reinicia el contenidor només si falla.
  • on-failure:<n>: Reinicia el contenidor només si falla un màxim de n vegades.

Exemple: Si volem que un contenidor es reiniciï sempre que falli o quan es reiniciï el servidor amfitrió, podem fer-ho amb la comanda següent:

docker run --restart always httpd

docker stop

Permet aturar un contenidor que està en execució.

Exemple: Per aturar un contenidor amb l’ID abc1102e802c:

docker stop abc1102e802c

També podem aturar tots els contenidors en execució amb la comanda següent:

docker stop $(docker ps -q)

docker start

Permet iniciar un contenidor que està aturat.

docker start <ID | NAME>

docker rm

Permet eliminar un contenidor que no està en execució.

Exemple amb nom:

docker rm wordpress

Exemple amb ID:

docker rm 99ed74b743ec

Per eliminar tots els contenidors que no estan en execució:

docker rm $(docker ps -aq)

docker rm -f

Permet eliminar un contenidor que està en execució, utilitzant el modificador -f.

Exemple amb nom:

docker rm -f wordpress

Per eliminar tots els contenidors, encara que estiguin en execució:

docker rm -f $(docker ps -aq)

Executar ordres dins d’un contenidor: docker exec

Permet executar ordres dins d’un contenidor que ja està en execució.

Exemple 1: Obrir una sessió interactiva dins del contenidor

docker exec -it webserver bash
  • Aquesta comanda ens permet entrar dins del contenidor com si fos una màquina virtual i executar ordres manualment.

Exemple 2: Executar una ordre concreta dins del contenidor

docker exec webserver ls /usr/share/nginx/html
  • Aquesta comanda llista els fitxers del directori /usr/share/nginx/html dins del contenidor sense obrir una sessió interactiva.

Copiem fitxers dins i fora d’un contenidor: docker cp

Per copiar una carpeta del teu ordinador local a dins d’un contenidor Docker que ja està en execució, pots utilitzar la comanda docker cp. Aquí tens la forma correcta i alguns exemples:

Sintaxi bàsica

docker cp <ruta_local> <contenidor>:/ruta/desti
  • <ruta_local>: ruta de la carpeta o fitxer del teu ordinador.
  • <contenidor>: nom o ID del contenidor Docker.
  • /ruta/desti: ruta dins del contenidor on vols copiar els fitxers.

Exemple pràctic

Suposem que vols copiar la carpeta local /home/jordi/web dins del contenidor webserver a /usr/local/apache2/htdocs/:

docker cp /home/jordi/web webserver:/usr/local/apache2/htdocs/
  • Això copiarà tots els fitxers i subcarpetes de /home/jordi/web dins del directori del contenidor.

Altres detalls importants

  1. Si vols copiar només un fitxer, només cal indicar el fitxer en lloc de la carpeta:
docker cp index.html webserver:/usr/local/apache2/htdocs/
  1. Si el directori de destí no existeix dins del contenidor, Docker el crearà automàticament.

  2. Per veure que els fitxers s’han copiat correctament, pots fer:

docker exec webserver ls /usr/local/apache2/htdocs/

Una forma molt habitual de copiar els fitxers és utilitzar la ruta relativa amb $(pwd) per copiar els fitxers del directori actual:

docker cp $(pwd) webserver:/usr/local/apache2/htdocs/

o bé, si vols copiar només un fitxer específic del directori actual:

docker cp $(pwd)/index.html webserver:/usr/local/apache2/htdocs/

Si ja estem situats dins del directori on tenim els fitxers, podem utilitzar . o el ./ per indicar el directori actual:

docker cp ./ webserver:/usr/local/apache2/htdocs/

Copia tots els fitxers del directori actual al directori actual dins del contenidor webserver.

Si ja teniem aixecat el contenidor webserver, ara hauríem de poder veure la landing page si visitem http://localhost al navegador.

Dockerfile

Aquest és un fitxer de text amb les instruccions per crear una imatge personalitzada. Es una part fonamental de Docker, la veurem en la propera sessió juntament amb docker-compose.

  • Fitxer de text amb les instruccions per crear una imatge personalitzada.
  • Exemple:
    FROM ubuntu:latest
    RUN apt-get update && apt-get install -y curl
    CMD ["bash"]
    

🔍 1.5 Funcionament Intern (Resum)

  1. El client executa una ordre (ex. docker run nginx).
  2. El Docker Daemon comprova si existeix la imatge localment.
  3. Si no la troba, la descarrega del Docker Hub.
  4. Crea un contenidor a partir de la imatge.
  5. Assigna recursos (CPU, memòria, xarxa) i el posa en execució.