diff --git a/01-contenedores/ejercicios/readme.md b/01-contenedores/ejercicios/readme.md
new file mode 100644
index 0000000..9cf7a42
--- /dev/null
+++ b/01-contenedores/ejercicios/readme.md
@@ -0,0 +1,388 @@
+# Laboratorio Docker
+
+Este laboratorio tiene como objetivo practicar los conceptos básicos de
+Docker:
+
+- Imágenes
+- Contenedores
+- Capas
+- Volúmenes
+- Redes
+- Docker Compose
+
+---
+
+# Entrega del laboratorio
+
+Este laboratorio debe entregarse mediante un **repositorio público en
+GitHub**.
+
+El repositorio debe contener un fichero:
+
+ README.md
+
+En este fichero deberás documentar:
+
+- Los pasos que has realizado
+- Los comandos utilizados
+- Una breve explicación de cada paso
+- Las respuestas a las preguntas del laboratorio
+
+El objetivo es que cualquier persona pueda **seguir tu documentación y
+reproducir el laboratorio**.
+
+Ejemplo de entrega:
+
+ https://github.com/usuario/docker-lab
+
+---
+
+# Criterios de evaluación
+
+El laboratorio se divide en:
+
+- **Parte obligatoria (necesaria para aprobar)**
+- **Parte opcional (para subir nota)**
+
+---
+
+## Parte obligatoria (mínimo para aprobar)
+
+Debes completar correctamente los siguientes ejercicios:
+
+- Ejercicio 1 --- Creando imágenes
+- Ejercicio 3 --- Volúmenes persistentes
+- Ejercicio 4 --- Bind mounts
+- Ejercicio 6 --- Redes privadas
+- Ejercicio 9 --- Docker Compose
+
+Si estos ejercicios **no funcionan o no están documentados**, el
+laboratorio **no se considerará aprobado**.
+
+---
+
+## Parte opcional (para subir nota)
+
+Estos ejercicios son **muy sencillos** y sirven para mejorar la nota.
+
+Puedes hacer uno o varios.
+
+- Ejercicio 2 --- Limpieza de imágenes
+- Ejercicio 5 --- Ver información de un volumen
+- Ejercicio 7 --- Investigar la red `none`
+- Ejercicio 8 --- Conectar un contenedor a dos redes
+
+También puedes hacer una pequeña mejora en Docker Compose.
+
+### Bonus sencillo
+
+Añade un servicio `nginx` a tu `docker-compose.yml`.
+
+Debe:
+
+- usar la imagen `nginx`
+- exponer el puerto `8080`
+- mostrar una página simple
+
+Ejemplo `index.html`:
+
+```html
+
Laboratorio Docker funcionando
+```
+
+Si al abrir:
+
+ http://localhost:8080
+
+aparece la página, el bonus estará completado.
+
+---
+
+# 1. Creando imágenes
+
+## Paso 1
+
+Ejecuta un contenedor basado en la imagen:
+
+ ubuntu
+
+Accede a la terminal del contenedor.
+
+Instala `curl`:
+
+```bash
+apt-get update
+apt-get install curl
+```
+
+Comprueba que funciona:
+
+```bash
+curl --version
+```
+
+---
+
+## Pregunta
+
+¿Con qué comando podrías **guardar los cambios del contenedor como una
+nueva imagen**?
+
+---
+
+## Paso 2 --- Dockerfile
+
+Crea un `Dockerfile` que haga lo mismo automáticamente.
+
+Ejemplo:
+
+```dockerfile
+FROM ubuntu
+
+RUN apt-get update && apt-get install -y curl
+```
+
+Construye la imagen y ejecuta un contenedor.
+
+Comprueba que `curl` está instalado.
+
+---
+
+## Pregunta
+
+¿Qué comando permite ver las **capas de una imagen Docker**?
+
+---
+
+# 2. Limpiando imágenes (opcional)
+
+Crea un `Dockerfile` basado en:
+
+ ubuntu
+
+Construye la imagen.
+
+Después modifica el Dockerfile para instalar:
+
+- `curl`
+- después `wget`
+
+Construye la imagen en cada cambio.
+
+Lista las imágenes:
+
+```bash
+docker images
+```
+
+Pregunta:
+
+¿Qué ocurre con las imágenes anteriores?
+
+---
+
+# 3. Volúmenes persistentes
+
+Ejecuta un contenedor de:
+
+ postgres
+
+Usa un volumen Docker montado en:
+
+ /var/lib/postgresql/data
+
+---
+
+## Crear tabla
+
+Conéctate a la base de datos.
+
+Crea la tabla:
+
+```sql
+CREATE TABLE items (
+ id SERIAL PRIMARY KEY,
+ name TEXT
+);
+```
+
+Inserta un registro:
+
+```sql
+INSERT INTO items(name) VALUES ('item1');
+```
+
+---
+
+## Comprobación
+
+1. Para el contenedor
+2. Elimina el contenedor
+3. Crea un nuevo contenedor usando **el mismo volumen**
+
+Comprueba que los datos siguen existiendo.
+
+---
+
+# 4. Bind mounts
+
+Crea un archivo en tu máquina:
+
+ index.html
+
+Ejemplo:
+
+```html
+Hola Docker
+```
+
+---
+
+Ejecuta un contenedor `nginx`:
+
+- mapea el puerto `80`
+- monta el archivo en:
+
+```{=html}
+
+```
+
+ /usr/share/nginx/html/index.html
+
+Abre el navegador.
+
+---
+
+Pregunta:
+
+¿Qué ocurre si modificas el archivo `index.html` en tu máquina?
+
+---
+
+# 5. Auditando volúmenes (opcional)
+
+Investiga:
+
+¿Qué comando permite ver **dónde guarda Docker los datos de un
+volumen**?
+
+---
+
+# 6. Creando redes privadas
+
+Crea una red llamada:
+
+ my-net
+
+---
+
+Arranca dos contenedores `ubuntu` en esa red.
+
+Instala `ping` si es necesario.
+
+Desde un contenedor intenta hacer:
+
+```bash
+ping otro_contenedor
+```
+
+---
+
+Pregunta
+
+¿Los contenedores pueden comunicarse entre sí?
+
+---
+
+# 7. Red none (opcional)
+
+Investiga:
+
+¿Para qué serviría ejecutar un contenedor con red:
+
+ none
+
+---
+
+# 8. Multi-network (opcional)
+
+Crea dos redes:
+
+ secure-zone
+ public-zone
+
+Arranca un contenedor en `public-zone`.
+
+Pregunta:
+
+¿Puedes conectarlo también a `secure-zone`?
+
+¿Qué comando usarías?
+
+---
+
+# 9. Docker Compose --- Compartiendo volúmenes
+
+Crea un fichero:
+
+ docker-compose.yml
+
+Con dos servicios.
+
+---
+
+## writer
+
+Debe:
+
+- montar un volumen en `/app/logs`
+- escribir un timestamp cada 30 segundos
+
+---
+
+## reader
+
+Debe:
+
+- montar el volumen en modo solo lectura
+- mostrar el contenido en consola
+
+---
+
+# 10. Docker Compose Profiles (opcional)
+
+Crea un `docker-compose.yml` con:
+
+- `postgres`
+- `pgadmin`
+
+Haz que `pgadmin` pueda conectarse a `postgres`.
+
+---
+
+Crea dos perfiles:
+
+### Perfil completo
+
+Levanta:
+
+- postgres
+- pgadmin
+
+### Perfil base
+
+Levanta solo:
+
+- postgres
+
+---
+
+# Resumen evaluación
+
+Nivel Requisitos
+
+---
+
+Aprobado Parte obligatoria completa
+Notable Parte obligatoria + ejercicios opcionales
+Sobresaliente Parte obligatoria + opcionales + bonus
diff --git a/02-kubernetes/ejercicios/readme.md b/02-kubernetes/ejercicios/readme.md
new file mode 100644
index 0000000..b6c3fe1
--- /dev/null
+++ b/02-kubernetes/ejercicios/readme.md
@@ -0,0 +1,77 @@
+# Ejercicios
+
+## 1. Naked Pod
+
+- Levanta un Pod desde consola, su imagen debe ser `nginx:alpine`.
+- Verfica que el Pod se está ejecutando
+- Borra el Pod.
+
+## 2. Self-Healing Deployment
+
+- Crea un Deployment con 3 replicas desde consola cuya imagen sea `httpd:alpine`.
+- Verifica que las 3 replicas están corriendo.
+- Elimina una de la réplicas. ¿Qué ocurre pasado un tiempo?
+- ¿Qué comando deberías usar para ver cómo aparacen las replicas en tiempo real?
+
+## 3. Zero-downtime Rollouts
+
+- Crea un Deployment usando la imagen `nginx:1.19`.
+- Actualiza la imagen a `nginx:1.21` ¿Qué opciones tienes para actualizar la imagen sin eliminar el Depolyment?
+- ¿Qué comando puedes usar para verificar el estado del *rollout*?
+
+## 4. PVC
+
+- Crea un `PersistentVolumClaim` solicitando 1Gi de alamacenamiento.
+- Monta el PVC en un POd y crea un fichero en el path `/temp`.
+- Elmina el Pod, crea un nuevo que monte el PVC anterior, verifica que el fichero sigue existiendo.
+
+## 5. StorageClass
+
+- Verifica si en tu cluster existe una `StorageClass default`.
+- Crea un volumen a través de la `StorageClass default`.
+- Verifica que el volumen se ha creado.
+
+## 6. Networking - ClusterIP
+
+- Crea un Deployment con la imagen `nginx`, expón el Deployment a través de un servicio ClusterIP.
+- Verifica que eres capaz de interactuar con `nginx` a través del servicio que has creado. Para ello usa una imagen `busybox`.
+- Si el Pod de `busybox` se hallará en otro `namespace` que FQN deberíamos usar.
+- ¿Cómo podemos aislar `namespaces` completamente en K8s?
+
+## 7. Networking - NodePort
+
+- Convierte el servicio anterior a NodePort.
+- Verifica `nginx` sigue siendo accesible.
+
+## 8. Networking - Ingress Controller
+
+Crea dos Deployments en `yaml` y exponlo a través de un servicio, también en `yaml`. Usa la imagen `hashicorp/http-echo`. Esta imagen permite pasar como argumento un 'echo'. Aquí tienes un ejemplo, usando un Pod:
+
+```yml
+kind: Pod
+apiVersion: v1
+metadata:
+ name: apple-app
+ labels:
+ app: apple
+spec:
+ containers:
+ - name: apple-app
+ image: hashicorp/http-echo
+ args:
+ - "-text=apple"
+```
+
+- El primer Deployment dará como echo la palabra *red*
+- El segundo Deployment dará como echo la palabra *yellow*
+- Crea un Ingress que exponga el primer Deployment en `example.com/red`, y el segundo en `example.com/yellow`.
+- Comprueba que funciona usando `curl -H "Host: example.com" ...`
+- Refactoriza el Ingress para que existan un Virtual Host por cada uno de los Deloyments.
+
+## 9. Networking - Gateway API
+
+Si quisieramos utilizar la [Gateway API](https://gateway-api.sigs.k8s.io/) en vez del Ingress del ejercicio anetrior, ¿qué consideraciones deberíamos tomar?
+
+## 10. Canary Deployment
+
+- Explica que es un Canary Deployment y los pasos para ejecutarlo en K8s.
\ No newline at end of file