Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Docker bàsic

Introducció

Docker és una plataforma que permet empaquetar aplicacions amb totes les seves dependències en contenidors (containers). Un contenidor és un entorn aïllat i portable que garanteix que l’aplicació funcionarà igual en qualsevol màquina, independentment del sistema operatiu o les configuracions locals.

Per què Docker?

Sense Docker:

  • “A la meva màquina funciona!” (però no a producció)
  • Instal·lar dependencies manualment en cada servidor
  • Conflictes de versions entre projectes
  • Dificultat per replicar entorns

Amb Docker:

  • Mateix entorn en desenvolupament i producció
  • Dependencies empaquetades amb l’aplicació
  • Aïllament entre projectes
  • Fàcil de compartir i desplegar

Contenidors vs Màquines Virtuals

Màquina Virtual (VM):

Màquina Virtual (VM)

Aplicació A

SO complet (Ubuntu)

Hypervisor

SO Host

Pes: ~GBs, arrencada: minuts

Contenidor Docker:

Contenidor Docker

Aplicació A

Dependencies

Docker Engine

SO Host

Pes: MBs, arrencada: segons

Diferències clau:

  • Contenidor: Comparteix el kernel del SO host, molt més lleuger
  • VM: Té el seu propi SO complet, més pesada i lenta

Conceptes fonamentals

Imatge (Image)

Una imatge és una plantilla de només lectura que conté:

  • Sistema operatiu mínim
  • Runtime (Python, Node, Java…)
  • Dependencies (llibreries)
  • Codi de l’aplicació
  • Configuració

Les imatges es construeixen a partir d’un Dockerfile.

Contenidor (Container)

Un contenidor és una instància en execució d’una imatge. Podem tenir múltiples contenidors de la mateixa imatge.

Analogia:

  • Imatge = Recepta de cuina (plantilla)
  • Contenidor = Pastís cuinat (instància)

Dockerfile

Un Dockerfile és un fitxer de text amb instruccions per construir una imatge.

Registre (Registry)

Un registre és un repositori d’imatges. El més popular és Docker Hub, però també podem tenir registres privats.

Instal·lació de Docker

Linux (Ubuntu/Debian)

# Actualitzar paquets sudo apt update # Instal·lar dependencies sudo apt install apt-transport-https ca-certificates curl software-properties-common # Afegir clau GPG oficial de Docker curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg # Afegir repositori de Docker echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # Instal·lar Docker sudo apt update sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin # Verificar instal·lació docker --version docker compose version # Opcional: executar Docker sense sudo sudo usermod -aG docker $USER # Logout i login per aplicar canvis

Verificar instal·lació

# Comprovar versió docker --version # Output: Docker version 24.0.0, build... # Test bàsic docker run hello-world # Hauria de descarregar i executar un contenidor de test

Comandes bàsiques de Docker

docker run: Executar un contenidor

# Forma bàsica docker run <imatge> # Exemple: executar Ubuntu docker run ubuntu echo "Hola Docker!" # Descarrega la imatge ubuntu, crea un contenidor, executa el comando, i s'atura # Mode interactiu (-it) docker run -it ubuntu bash # -i: interactiu (mantenir STDIN obert) # -t: terminal (assignar una pseudo-TTY) # Ara estem dins del contenidor amb una shell bash! # Mode detached (-d): en segon pla docker run -d nginx # Executa nginx en background i retorna l'ID del contenidor # Assignar nom (--name) docker run -d --name my_nginx nginx # Ara podem referir-nos al contenidor pel nom "my_nginx" # Mapejar ports (-p) docker run -d -p 8080:80 nginx # -p host_port:container_port # Accedir a http://localhost:8080 ’ port 80 del contenidor # Eliminar automàticament després de parar (--rm) docker run --rm ubuntu echo "Aquest contenidor s'eliminarà automàticament"

Resum de flags comuns:

  • -d: Detached (background)
  • -it: Interactive + TTY (shell interactiva)
  • -p: Publicar ports (host:container)
  • --name: Assignar nom
  • --rm: Eliminar automàticament després de parar
  • -e: Variables d’entorn
  • -v: Muntar volums

docker ps: Llistar contenidors

# Contenidors en execució docker ps # Tots els contenidors (inclosos parats) docker ps -a # Només IDs docker ps -q # Output exemple: # CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # abc123def456 nginx "/docker-entrypoint.&" 2 hours ago Up 2 hours 0.0.0.0:8080->80/tcp my_nginx

docker images: Llistar imatges

# Llistar totes les imatges locals docker images # Output exemple: # REPOSITORY TAG IMAGE ID CREATED SIZE # nginx latest abc123def456 2 weeks ago 142MB # ubuntu 22.04 def456ghi789 3 weeks ago 77.8MB

docker stop / start / restart: Controlar contenidors

# Aturar un contenidor docker stop <container_id o nom> docker stop my_nginx # Iniciar un contenidor aturat docker start my_nginx # Reiniciar docker restart my_nginx # Aturar tots els contenidors en execució docker stop $(docker ps -q)

docker rm / rmi: Eliminar contenidors i imatges

# Eliminar un contenidor (ha d'estar parat) docker rm <container_id o nom> docker rm my_nginx # Forçar eliminació (encara que estigui en execució) docker rm -f my_nginx # Eliminar tots els contenidors parats docker container prune # Eliminar una imatge docker rmi <imatge:tag> docker rmi nginx:latest # Eliminar imatges no utilitzades docker image prune # Eliminar tot (contenidors, imatges, volums, xarxes no usats) docker system prune -a

docker logs: Veure logs

# Veure logs d'un contenidor docker logs <container_id o nom> docker logs my_nginx # Seguir logs en temps real (-f) docker logs -f my_nginx # Últimes N línies (--tail) docker logs --tail 50 my_nginx # Logs amb timestamps (-t) docker logs -t my_nginx

docker exec: Executar comandos dins d’un contenidor en execució

# Executar un comando docker exec <container_id o nom> <comando> docker exec my_nginx ls /usr/share/nginx/html # Obrir una shell interactiva docker exec -it my_nginx bash # Ara estem dins del contenidor! # Executar com un usuari específic docker exec -u root my_nginx whoami

docker inspect: Inspeccionar un contenidor o imatge

# Veure informació detallada docker inspect my_nginx # Filtrar per un camp específic docker inspect --format='{{.NetworkSettings.IPAddress}}' my_nginx # Output: 172.17.0.2

Crear la teva primera imatge: Dockerfile

Un Dockerfile és una recepta per construir una imatge. Conté instruccions com ara quin sistema operatiu usar, quines dependencies instal·lar, i quin codi copiar.

Estructura bàsica d’un Dockerfile

# Comentari: línia que comença amb # # FROM: imatge base (obligatòria, sempre la primera instrucció) FROM python:3.11-slim # WORKDIR: directori de treball dins del contenidor WORKDIR /app # COPY: copiar fitxers del host al contenidor COPY requirements.txt . # RUN: executar comandos durant la construcció RUN pip install --no-cache-dir -r requirements.txt # COPY de nou: copiar el codi de l'aplicació COPY . . # ENV: definir variables d'entorn ENV PORT=8000 # EXPOSE: documentar quin port exposa l'aplicació (no publica el port!) EXPOSE 8000 # CMD: comando per defecte quan s'executa el contenidor CMD ["python", "app.py"]

Instruccions principals

FROM: Imatge base

# Imatge oficial de Python FROM python:3.11-slim # Imatge oficial de Node.js FROM node:18-alpine # Imatge oficial d'Ubuntu FROM ubuntu:22.04 # Versions específiques (recomanat per reproducibilitat) FROM python:3.11.5-slim

Etiquetes comuns:

  • latest: Última versió (evitar en producció)
  • 3.11: Versió específica
  • 3.11-slim: Versió lleugera (sense moltes dependencies)
  • 3.11-alpine: Versió mínima basada en Alpine Linux (la més petita)

WORKDIR: Directori de treball

# Canvia el directori de treball WORKDIR /app # A partir d'aquí, totes les instruccions es fan a /app COPY . . # Copia al directori actual (/app)

COPY i ADD: Copiar fitxers

# COPY: copiar fitxers/directoris del host al contenidor COPY requirements.txt /app/ COPY src/ /app/src/ COPY . . # Tot el directori actual ’ directori de treball # ADD: com COPY però també pot descomprimir tar i descarregar URLs ADD https://example.com/file.tar.gz /app/ ADD archive.tar.gz /app/ # Descomprimeix automàticament

Recomanació: Usa COPY sempre que sigui possible. ADD només per descomprimir tar.

RUN: Executar comandos

# Executar comandos durant la construcció de la imatge RUN apt-get update && apt-get install -y curl # Instal·lar dependencies de Python RUN pip install --no-cache-dir -r requirements.txt # Múltiples comandos (recomanat: reduir capes) RUN apt-get update && \ apt-get install -y curl wget && \ apt-get clean && \ rm -rf /var/lib/apt/lists/*

Millor pràctica: Combinar comandos relacionats amb && per reduir el nombre de capes.

ENV: Variables d’entorn

# Definir variables d'entorn ENV PORT=8000 ENV MODEL_PATH=/models/model.pkl ENV LOG_LEVEL=info # Usar variables RUN echo "Port: $PORT"

EXPOSE: Documentar ports

# Indica quin port usa l'aplicació (només documentació!) EXPOSE 8000 # NO publica el port automàticament # Cal usar -p en docker run

CMD i ENTRYPOINT: Comando per defecte

CMD: Comando per defecte (pot ser sobreescrit)

# Format exec (recomanat) CMD ["python", "app.py"] # Format shell CMD python app.py

ENTRYPOINT: Comando fix (arguments en docker run s’afegeixen)

# Executar sempre python amb el script que es passi ENTRYPOINT ["python"] CMD ["app.py"] # Argument per defecte # docker run myimage ’ python app.py # docker run myimage test.py ’ python test.py

Recomanació: Usa CMD per simplicitat, tret que necessitis el comportament d’ENTRYPOINT.

Exemple complet: Aplicació Python

Estructura del projecte:

myapp/ Dockerfile requirements.txt app.py src/ utils.py

requirements.txt:

flask==3.0.0 requests==2.31.0

app.py:

from flask import Flask app = Flask(__name__) @app.route("/") def home(): return "Hola des de Docker!" if __name__ == "__main__": app.run(host="0.0.0.0", port=8000)

Dockerfile:

# Imatge base FROM python:3.11-slim # Directori de treball WORKDIR /app # Copiar requirements i instal·lar dependencies COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # Copiar el codi de l'aplicació COPY app.py . COPY src/ ./src/ # Port que usa l'aplicació EXPOSE 8000 # Comando per executar l'aplicació CMD ["python", "app.py"]

Construir i executar la imatge

# Construir la imatge docker build -t myapp:1.0 . # -t: tag (nom:versió) # .: context (directori actual) # Executar un contenidor docker run -d -p 8000:8000 --name myapp_container myapp:1.0 # Accedir a l'aplicació curl http://localhost:8000 # Output: Hola des de Docker! # Veure logs docker logs -f myapp_container # Aturar i eliminar docker stop myapp_container docker rm myapp_container

.dockerignore: Excloure fitxers

Crea un fitxer .dockerignore per evitar copiar fitxers innecessaris:

# .dockerignore __pycache__/ *.pyc *.pyo *.pyd .git/ .gitignore .venv/ venv/ env/ *.md tests/ .pytest_cache/ .DS_Store

Beneficis:

  • Imatges més petites
  • Construcció més ràpida
  • Evita secrets accidentals

Volums: Persistència de dades

Per defecte, les dades dins d’un contenidor es perden quan s’elimina. Els volums permeten persistir dades.

Tipus de volums

1. Named volumes (recomanat)

Gestionats per Docker:

# Crear un volum docker volume create my_data # Usar el volum en un contenidor docker run -d -v my_data:/app/data myapp:1.0 # my_data: nom del volum # /app/data: path dins del contenidor # Llistar volums docker volume ls # Inspeccionar volum docker volume inspect my_data # Eliminar volum docker volume rm my_data

2. Bind mounts (per desenvolupament)

Muntar un directori del host:

# Muntar directori actual al contenidor docker run -d -v $(pwd)/data:/app/data myapp:1.0 # $(pwd)/data: directori del host # /app/data: directori del contenidor # Recomanat: usar path absolut docker run -d -v /home/user/project/data:/app/data myapp:1.0

Ús típic: Desenvolupament (canvis en local es reflecteixen immediatament).

3. Anonymous volumes

# Docker crea un volum anònim docker run -d -v /app/data myapp:1.0

Comparativa:

TipusQuan usarGestió
Named volumeProducció, dades persistentsDocker
Bind mountDesenvolupament, compartir fitxersHost
AnonymousRara vegada (dades temporals)Docker

Exemple: Persistir logs

# Crear volum per logs docker volume create app_logs # Executar amb volum docker run -d \ --name myapp \ -p 8000:8000 \ -v app_logs:/app/logs \ myapp:1.0 # Els logs es guarden a app_logs, persisteixen després d'eliminar el contenidor

Variables d’entorn

Les variables d’entorn permeten configurar l’aplicació sense canviar el codi.

Passar variables d’entorn

# Opció 1: -e o --env (una per una) docker run -d \ -e LOG_LEVEL=debug \ -e MAX_WORKERS=4 \ myapp:1.0 # Opció 2: --env-file (des d'un fitxer) docker run -d --env-file .env myapp:1.0

Fitxer .env:

LOG_LEVEL=debug MAX_WORKERS=4 DATABASE_URL=postgresql://localhost/mydb

Usar variables dins del contenidor

# app.py import os log_level = os.getenv('LOG_LEVEL', 'info') # 'info' per defecte max_workers = int(os.getenv('MAX_WORKERS', '2')) print(f"Log level: {log_level}, Workers: {max_workers}")

Bones pràctiques

  1. Mai commitejis secrets (passwords, API keys) al codi
  2. Usa variables d’entorn per configuració
  3. Defineix valors per defecte raonables
  4. Documenta les variables necessàries

Docker Compose: Orquestració simplificada

Docker Compose és una eina per definir i executar aplicacions amb múltiples contenidors usant un fitxer YAML. Simplifica el treball amb contenidors.

Per què Docker Compose?

Sense Compose: Comandos llargs i difícils de recordar

docker run -d --name app -p 8000:8000 -e LOG_LEVEL=info -v $(pwd)/models:/models myapp:1.0 docker run -d --name db -p 5432:5432 -e POSTGRES_PASSWORD=secret postgres:15

Amb Compose: Un fitxer YAML i un comando simple

# docker-compose.yml services: app: image: myapp:1.0 ports: - "8000:8000" environment: - LOG_LEVEL=info volumes: - ./models:/models db: image: postgres:15 environment: - POSTGRES_PASSWORD=secret
# Aixecar tots els serveis docker-compose up -d

Estructura bàsica de docker-compose.yml

# Versió del format (opcional en versions recents) version: '3.8' # Definició de serveis (contenidors) services: # Nom del servei app: # Imatge a usar image: myapp:1.0 # O construir des d'un Dockerfile build: . # Ports (host:contenidor) ports: - "8000:8000" # Variables d'entorn environment: - LOG_LEVEL=info - MAX_WORKERS=4 # Volums volumes: - ./models:/app/models - app_logs:/app/logs # Dependències (iniciar després de...) depends_on: - db # Política de reinici restart: unless-stopped db: image: postgres:15 environment: - POSTGRES_PASSWORD=secret volumes: - postgres_data:/var/lib/postgresql/data # Volums (declaració global) volumes: app_logs: postgres_data:

Comandes de Docker Compose

# Aixecar serveis (construir si cal) docker-compose up # Mode detached (background) docker-compose up -d # Reconstruir imatges abans d'aixecar docker-compose up --build # Aturar serveis (contenidors segueixen existint) docker-compose stop # Aixecar serveis parats docker-compose start # Aturar i eliminar contenidors docker-compose down # Eliminar també volums docker-compose down -v # Veure logs de tots els serveis docker-compose logs # Logs en temps real docker-compose logs -f # Logs d'un servei específic docker-compose logs -f app # Llistar serveis docker-compose ps # Executar comando en un servei docker-compose exec app bash # Reconstruir un servei docker-compose build app # Escalar un servei (múltiples instàncies) docker-compose up -d --scale app=3

Exemple complet: API amb base de dades

Estructura del projecte:

project/ docker-compose.yml Dockerfile app.py requirements.txt models/ model.pkl

Dockerfile:

FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app.py . EXPOSE 8000 CMD ["python", "app.py"]

docker-compose.yml:

version: '3.8' services: api: build: . container_name: ml_api ports: - "8000:8000" environment: - MODEL_PATH=/models/model.pkl - DATABASE_URL=postgresql://user:pass@db:5432/predictions - LOG_LEVEL=info volumes: - ./models:/models:ro # :ro = read-only - ./logs:/app/logs depends_on: - db restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s db: image: postgres:15 container_name: ml_db environment: - POSTGRES_USER=user - POSTGRES_PASSWORD=pass - POSTGRES_DB=predictions volumes: - postgres_data:/var/lib/postgresql/data ports: - "5432:5432" restart: unless-stopped healthcheck: test: ["CMD-SHELL", "pg_isready -U user"] interval: 10s timeout: 5s retries: 5 volumes: postgres_data:

Ús:

# Aixecar tots els serveis docker-compose up -d # Veure estat docker-compose ps # NAME IMAGE STATUS PORTS # ml_api project_api Up (healthy) 0.0.0.0:8000->8000/tcp # ml_db postgres:15 Up (healthy) 0.0.0.0:5432->5432/tcp # Veure logs docker-compose logs -f api # Accedir a l'API curl http://localhost:8000/health # Aturar tot docker-compose down

Health checks

Els health checks verifiquen que el contenidor està funcionant correctament:

services: api: image: myapp:1.0 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s # Cada quan comprovar timeout: 10s # Temps màxim d'espera retries: 3 # Quants errors abans de marcar unhealthy start_period: 40s # Temps d'espera inicial (arrencada)

Test commands comuns:

# HTTP endpoint test: ["CMD", "curl", "-f", "http://localhost:8000/health"] # PostgreSQL test: ["CMD-SHELL", "pg_isready -U user"] # Redis test: ["CMD", "redis-cli", "ping"] # MySQL test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]

Veure estat de health:

docker-compose ps # STATUS mostra: Up (healthy), Up (unhealthy), Up (starting) docker inspect ml_api --format='{{.State.Health.Status}}' # Output: healthy

Variables d’entorn amb fitxer .env

Crear un fitxer .env (no comitear a git!):

# .env LOG_LEVEL=debug MAX_WORKERS=4 DATABASE_PASSWORD=super_secret_123 MODEL_VERSION=1.2.0

docker-compose.yml:

services: api: build: . env_file: .env # Carregar variables des de .env environment: - DATABASE_URL=postgresql://user:${DATABASE_PASSWORD}@db:5432/predictions

Accedir a variables:

# Docker Compose carrega automàticament .env si existeix docker-compose up -d

Xarxes (Networks)

Docker Compose crea automàticament una xarxa per als serveis. Els contenidors es poden comunicar pel nom del servei:

services: api: # Pot accedir a la base de dades a db:5432 environment: - DATABASE_URL=postgresql://user:pass@db:5432/predictions db: # El servei "db" és accessible com "db" dins la xarxa

Xarxes personalitzades (avançat):

services: api: networks: - frontend - backend db: networks: - backend networks: frontend: backend:

Millors pràctiques

1. Imatges petites i eficients

# BÉ: Usar imatges -slim o -alpine FROM python:3.11-slim # MALAMENT: Imatge completa (molt més gran) FROM python:3.11 # BÉ: Netejar després d'instal·lar RUN apt-get update && \ apt-get install -y curl && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* # MALAMENT: Deixar cache RUN apt-get update RUN apt-get install -y curl

2. Ordre de les capes (cache)

Docker crea una capa per cada instrucció. Si una capa canvia, les següents es reconstrueixen.

# BÉ: Dependencies primer (canvien poc) COPY requirements.txt . RUN pip install -r requirements.txt COPY . . # Codi (canvia sovint) # MALAMENT: Copiar tot primer COPY . . # Si canvia qualsevol fitxer, pip install es torna a executar! RUN pip install -r requirements.txt

3. No executar com root

# Crear usuari no-root RUN useradd -m -u 1000 appuser # Canviar ownership RUN chown -R appuser:appuser /app # Canviar a aquest usuari USER appuser # A partir d'aquí, tot s'executa com appuser CMD ["python", "app.py"]

4. Usar .dockerignore

# .dockerignore **/.git **/__pycache__ **/.venv **/.pytest_cache *.md tests/ .env

5. Secrets segurs

# L MAI fer això ENV DATABASE_PASSWORD=super_secret # Usar variables d'entorn o Docker secrets docker run -e DATABASE_PASSWORD=secret myapp:1.0 # O fitxer .env (no comitear!) docker-compose --env-file .env up

6. Multi-stage builds (avançat)

Per imatges encara més petites:

# Stage 1: Build FROM python:3.11 as builder WORKDIR /app COPY requirements.txt . RUN pip install --user -r requirements.txt # Stage 2: Runtime FROM python:3.11-slim WORKDIR /app COPY --from=builder /root/.local /root/.local COPY . . ENV PATH=/root/.local/bin:$PATH CMD ["python", "app.py"]

Debugging i troubleshooting

Contenidor no arrenca

# Veure logs docker logs <container_id> # Veure últimes línies docker logs --tail 50 <container_id> # Intentar executar-lo en mode interactiu docker run -it myapp:1.0 bash # Ara podem debugar dins del contenidor

Port no accessible

# Verificar que el port està publicat docker ps # Hauria de mostrar: 0.0.0.0:8000->8000/tcp # Verificar dins del contenidor docker exec -it <container> curl localhost:8000 # Verificar firewall/ports del host sudo netstat -tulpn | grep 8000

Problemes de permisos amb volums

# Veure ownership dels fitxers docker exec <container> ls -la /app/data # Canviar ownership (dins Dockerfile) RUN chown -R appuser:appuser /app/data

Neteja d’espai

# Veure ús d'espai docker system df # Eliminar contenidors parats docker container prune # Eliminar imatges no usades docker image prune # Eliminar tot (contenidors, imatges, volums, xarxes) docker system prune -a --volumes #  Alerta: elimina TOTS els volums!

Inspeccionar xarxes

# Llistar xarxes docker network ls # Inspeccionar xarxa docker network inspect <network_name> # Veure IP d'un contenidor docker inspect --format='{{.NetworkSettings.IPAddress}}' <container>

Workflow recomanat per ML

# 1. Desenvolupament local # Editar codi, provar amb Docker Compose docker-compose up --build # 2. Tests # Executar tests dins del contenidor docker-compose exec api pytest tests/ # 3. Verificar health curl http://localhost:8000/health # 4. Veure logs docker-compose logs -f api # 5. Quan tot funciona, preparar per producció # Construir imatge amb tag de versió docker build -t myapp:1.2.0 . # 6. Desplegar (varies opcions): # - Pujar a un registre privat i descarregar al servidor # - Copiar la imatge directament (docker save/load) # - Usar CI/CD per automatitzar # 7. En producció docker-compose -f docker-compose.prod.yml up -d

Resum de comandes essencials

# === IMAGES === docker images # Llistar imatges docker build -t nom:tag . # Construir imatge docker rmi nom:tag # Eliminar imatge # === CONTAINERS === docker ps # Contenidors en execució docker ps -a # Tots els contenidors docker run -d -p 8000:8000 nom # Executar contenidor docker stop <id> # Aturar docker start <id> # Iniciar docker restart <id> # Reiniciar docker rm <id> # Eliminar docker logs -f <id> # Veure logs docker exec -it <id> bash # Entrar al contenidor # === VOLUMES === docker volume ls # Llistar volums docker volume create nom # Crear volum docker volume rm nom # Eliminar volum # === COMPOSE === docker-compose up -d # Aixecar serveis docker-compose up --build # Reconstruir i aixecar docker-compose down # Aturar i eliminar docker-compose logs -f # Logs docker-compose ps # Estat dels serveis docker-compose exec servei bash # Entrar a un servei # === NETEJA === docker system prune # Netejar tot no usat docker system df # Veure ús d'espai

Recursos addicionals