Pas 3 - Contenidors en segon pla
Els contenidors del pas 1 feien una tasca i s'aturaven. Un servei, en canvi (un servidor web, una base de dades), ha d'estar funcionant contínuament. En aquest pas executarem un servidor NGINX en segon pla (mode detached o dimoni) i aprendrem a gestionar-lo.
Objectius del pas
- Veure la diferència entre executar en primer pla i en segon pla (
-d). - Donar nom als contenidors i gestionar-ne el cicle de vida:
stop,start,restart,rm. - Consultar logs i executar ordres dins d'un contenidor en marxa (
logs,exec). - Comprovar que els canvis fets dins d'un contenidor es perden quan s'elimina.
3.1 Primer pla: el terminal queda ocupat
Aquesta vegada el contenidor no s'atura: NGINX és un servidor i el seu procés principal es queda escoltant peticions. El terminal queda "segrestat" mostrant els logs del servidor. Si premeu ++ctrl+c++, el procés rep el senyal, acaba, i el contenidor s'atura.
3.2 Segon pla: -d
-d(detached): el contenidor s'executa en segon pla i Docker ens retorna el terminal, mostrant només l'ID del contenidor.--name web: li donem un nom per poder-nos-hi referir fàcilment. Els noms són únics: si torneu a executar la comanda, Docker es queixarà que el nomwebja està en ús.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b7e2f4c1a9d8 nginx:1.27-alpine "/docker-entrypoint.…" 10 seconds ago Up 9 seconds 80/tcp web
Ara l'estat és Up. La columna PORTS diu 80/tcp: NGINX escolta al port 80 dins del contenidor, però encara no hi podem accedir des de fora. Ho resoldrem al Pas 4.
3.3 Mirar què passa dins
Logs: tot el que el procés principal escriu per la sortida estàndard queda registrat.
docker logs web # tots els logs fins ara
docker logs -f web # segueix els logs en temps real (Ctrl+C per sortir)
docker logs --tail 20 web # només les últimes 20 línies
Executar ordres dins d'un contenidor que ja està funcionant:
docker exec web ls /usr/share/nginx/html
docker exec web cat /etc/os-release
docker exec -it web sh # obre un shell interactiu (alpine no té bash)
Dins del shell, proveu ps. Veureu que el procés amb PID 1 és nginx: master process: és el procés principal. Mentre ell visqui, el contenidor viurà. Sortiu amb exit: ara el contenidor no s'atura, perquè el sh que tanqueu no és el procés principal, només un procés afegit amb exec.
Consum de recursos i detalls:
docker stats web # CPU, memòria i xarxa en temps real
docker top web # processos del contenidor vistos des de l'amfitrió
docker inspect web # tota la configuració en JSON (IP, muntatges, estat...)
docker run o docker exec?
docker run crea un contenidor nou a partir d'una imatge. docker exec executa una ordre dins d'un contenidor que ja existeix i està en marxa. Un error típic és fer docker run -it nginx sh per "entrar al servidor" i acabar dins d'un contenidor nou i buit, diferent del que volíeu inspeccionar.
3.4 El cicle de vida d'un contenidor
docker stop web # atura (envia SIGTERM i, després de 10 s, SIGKILL)
docker ps -a # estat: Exited
docker start web # torna a arrencar EL MATEIX contenidor
docker restart web # stop + start
docker pause web # congela els processos (sense aturar-los)
docker unpause web
docker rm web # error: no es pot eliminar un contenidor en marxa
docker rm -f web # atura i elimina
stateDiagram-v2
[*] --> Created: docker create
Created --> Running: docker start
[*] --> Running: docker run
Running --> Paused: docker pause
Paused --> Running: docker unpause
Running --> Exited: docker stop / el proces acaba
Exited --> Running: docker start
Exited --> [*]: docker rm
Running --> [*]: docker rm -f
docker run = docker create + docker start
docker create prepara el contenidor sense arrencar-lo (estat Created). És útil per configurar-lo abans d'engegar-lo, però a la pràctica gairebé sempre fareu servir docker run.
Polítiques de reinici
Què passa si l'amfitrió es reinicia? Per defecte, els contenidors queden aturats. Amb --restart podem indicar què ha de fer Docker:
| Política | Comportament |
|---|---|
no (per defecte) |
No es reinicia mai automàticament |
on-failure[:N] |
Es reinicia si el procés acaba amb error (fins a N intents) |
always |
Es reinicia sempre, també en arrencar el dimoni de Docker |
unless-stopped |
Com always, excepte si l'heu aturat vosaltres manualment |
3.5 Els contenidors són efímers
Aquest és un dels experiments més importants del bloc. Modifiquem la pàgina d'inici del servidor des de dins del contenidor:
docker exec web sh -c 'echo "<h1>Pagina modificada</h1>" > /usr/share/nginx/html/index.html'
docker exec web cat /usr/share/nginx/html/index.html
Ara aturem i tornem a arrencar el mateix contenidor:
docker stop web
docker start web
docker exec web cat /usr/share/nginx/html/index.html # el canvi continua aquí
El canvi es manté, perquè és a la capa d'escriptura del contenidor, i aquesta capa existeix mentre existeixi el contenidor. Però ara l'eliminem i en creem un de nou:
docker rm -f web
docker run -d --name web nginx:1.27-alpine
docker exec web cat /usr/share/nginx/html/index.html # torna a ser la pàgina original
El canvi s'ha perdut. El contenidor nou parteix de la imatge, que no ha canviat mai, amb una capa d'escriptura nova i buida.
flowchart LR
I[(Imatge nginx)] --> A[Contenidor web 1<br/>index.html modificat]
A -->|docker rm| X((eliminat))
I --> B[Contenidor web 2<br/>index.html original]
classDef img fill:#2563EB,stroke:#1E40AF,color:#FFFFFF
classDef cont fill:#16A34A,stroke:#166534,color:#FFFFFF
classDef del fill:#64748B,stroke:#475569,color:#FFFFFF
class I img
class A,B cont
class X del
Aquesta és la raó de ser de dos passos posteriors:
- Si volem que un contingut propi formi part de la imatge, cal construir una imatge personalitzada (Pas 8).
- Si volem que unes dades sobrevisquin al contenidor (una base de dades, fitxers pujats...), cal guardar-les en un volum (Pas 6).
Miniactivitat - Cicle de vida
- Arrenqueu dos contenidors NGINX en segon pla anomenats
web1iweb2. Pot tenir cadascun el seu servidor al port 80 intern sense conflicte? Per què? - Obriu un shell dins de
web1i trobeu quin és el PID 1. - Executeu
docker run -d alpine:3.20. Per què apareix adocker ps -acom aExitedsi l'hem arrencat amb-d? Com podríeu mantenir-lo en marxa? (pista:sleep infinity). - Repetiu l'experiment de la secció 3.5 i expliqueu amb les vostres paraules per què el canvi sobreviu a
stop/startperò no arm.
3.6 Neteja
Resum del pas
| Comanda | Què fa |
|---|---|
docker run -d --name NOM IMATGE |
Contenidor en segon pla amb nom |
docker logs [-f] NOM |
Logs del procés principal |
docker exec [-it] NOM ordre |
Executa una ordre dins d'un contenidor en marxa |
docker stop / start / restart NOM |
Atura / arrenca / reinicia el mateix contenidor |
docker rm [-f] NOM |
Elimina el contenidor (i la seva capa d'escriptura) |
docker stats, docker top, docker inspect |
Recursos, processos i configuració |
--restart unless-stopped |
Reinicia automàticament el contenidor |
Següent pas: tenim un servidor web funcionant... però no hi podem accedir. Al Pas 4 el publicarem.