Docker ha pasado de ser una novedad tecnológica a una piedra angular en el desarrollo y la infraestructura de software. Pero, ¿qué es exactamente, cómo funciona y por qué es tan omnipresente? Acompáñame en este viaje para entenderlo en profundidad. Así mismo, vista nuestro blog para saber más de tecnología.

Historia de Docker: Del Aislamiento a la Revolución
¿Cuándo se creó Docker y cuál fue su propósito inicial?
Docker fue lanzado por Solomon Hykes en PyCon 2013. Inicialmente, Docker nació como un proyecto interno de dotCloud, una empresa de plataforma como servicio (PaaS). Su propósito original era estandarizar y simplificar el despliegue de aplicaciones para sus clientes. dotCloud ya utilizaba tecnología de contenedores (Linux Containers – LXC) internamente, pero el proceso era complejo y difícil de manejar. Docker buscó abstraer esta complejidad, proporcionando una interfaz sencilla y amigable para que los desarrolladores pudieran empaquetar sus aplicaciones y sus dependencias de forma consistente.
¿Cómo evolucionó Docker desde sus inicios hasta convertirse en una herramienta clave en el desarrollo de software?
La evolución de Docker fue meteórica debido a su simplicidad y el concepto de «contenedor portable».
- Abstracción de LXC: En sus inicios, Docker se basó en LXC, pero pronto desarrolló su propia tecnología de virtualización a nivel de sistema operativo, el «containerd», que ofrecía mejor aislamiento y portabilidad.
- Popularización de los Contenedores: Docker no inventó los contenedores, pero los popularizó masivamente. Hizo que la tecnología de contenedores fuera accesible y fácil de usar para una audiencia mucho más amplia de desarrolladores y operadores, democratizando así las prácticas de DevOps.
- Ecosistema y Herramientas: La comunidad creció rápidamente. Docker introdujo
Dockerfile
(para definir imágenes), Docker Hub (para compartir imágenes) y Docker Compose (para orquestación de múltiples contenedores). - Estándares y Colaboración: Para evitar la fragmentación, Docker contribuyó a la creación de estándares de la industria como el Open Container Initiative (OCI), que define formatos de imagen y tiempo de ejecución de contenedores. Esto permitió que otras herramientas pudieran interactuar con los contenedores de Docker.
- Adopción Empresarial: Grandes empresas comenzaron a adoptar Docker por sus beneficios en la CI/CD (Integración Continua/Entrega Continua), la portabilidad y la eficiencia de recursos. La aparición de orquestadores como Kubernetes (originalmente desarrollado por Google para gestionar miles de contenedores internamente) y Docker Swarm, catapultó aún más la adopción de la contenerización a nivel de producción.
En resumen, Docker evolucionó de una herramienta interna a un estándar de facto para la contenerización, simplificando drásticamente el ciclo de vida del desarrollo y despliegue de software.

¿Qué es Docker?: La Filosofía del Contenedor
¿Qué son los contenedores en el contexto de Docker y en qué se diferencian de las máquinas virtuales?
En el contexto de Docker, un contenedor es una unidad de software estandarizada que empaqueta todo el código de una aplicación, junto con todas sus dependencias (bibliotecas, configuraciones, variables de entorno, etc.), de modo que la aplicación funcione de manera rápida y fiable de un entorno informático a otro. Piensa en ello como una «caja» ligera y auto-suficiente para tu aplicación.
Diferencias clave con las Máquinas Virtuales (VMs)
Característica | Contenedores (Docker) | Máquinas Virtuales (VMs) |
---|---|---|
Aislamiento | A nivel del sistema operativo | A nivel de hardware |
Sistema Operativo | Comparten el SO del host (Kernel) | Cada VM tiene su propio SO completo (SO invitado) |
Hypervisor | No requieren un hypervisor; usan un «motor de contenedor» (Docker Engine) | Requieren un hypervisor (ej. VMware, VirtualBox, Hyper-V) |
Tamaño | Muy ligeros (MBs) | Pesados (GBs) |
Inicio | Rápidos (segundos o milisegundos) | Lentos (minutos) |
Recursos | Consumen menos recursos (CPU, RAM) | Consumen muchos más recursos |
Portabilidad | Altamente portables (funciona igual en cualquier host con Docker) | Menos portables (el archivo de la VM es grande y específico del hypervisor) |
En esencia, los contenedores virtualizan el sistema operativo, mientras que las máquinas virtuales virtualizan el hardware. Esto hace que los contenedores sean mucho más eficientes, ligeros y rápidos.
¿Cómo funciona Docker?: Componentes y Flujo
¿Cuáles son los componentes clave de la arquitectura de Docker (Daemon, Cliente, Registro) y cómo interactúan?
La arquitectura de Docker se basa en una estructura cliente-servidor:
- Docker Daemon (dockerd): Es el servidor de Docker. Se ejecuta en el sistema host y es responsable de construir, ejecutar y gestionar los objetos de Docker (imágenes, contenedores, redes, volúmenes). Escucha las solicitudes de la API de Docker.
- Docker Client (docker): Es la interfaz de línea de comandos (CLI) principal que la mayoría de los usuarios utilizan para interactuar con Docker. Envía comandos al Docker Daemon a través de la API REST. Cuando escribes
docker run
odocker build
, el cliente se comunica con el daemon. - Docker Registry (Registro): Es un servicio que almacena y distribuye imágenes Docker. El registro público más conocido es Docker Hub. Cuando «pull» (descargas) una imagen, la obtienes de un registro; cuando «push» (subes) una imagen, la envías a un registro.
Interacción:
- El Docker Client envía un comando (ej.
docker run ubuntu
) al Docker Daemon. - El Docker Daemon procesa la solicitud. Si necesita una imagen (ej.
ubuntu
) que no tiene localmente, se conecta al Docker Registry (por defecto Docker Hub) para descargarla. - Una vez que el Daemon tiene la imagen, la utiliza para crear y ejecutar el contenedor.
- El Daemon también gestiona otros objetos como volúmenes (para datos persistentes) y redes (para la comunicación entre contenedores).

¿Cómo se utilizan los Dockerfiles para construir imágenes de Docker?
Un Dockerfile es un archivo de texto simple que contiene una serie de instrucciones para construir una imagen Docker. Es como una receta para crear tu «caja» de aplicación. Cada instrucción en el Dockerfile crea una capa en la imagen, lo que permite la reutilización y el almacenamiento en caché eficientes.
Ejemplo de un Dockerfile simple:
Dockerfile
# Usa una imagen base de Node.js con la versión 18
FROM node:18-alpine
# Establece el directorio de trabajo dentro del contenedor
WORKDIR /app
# Copia los archivos de definición de dependencias y paquetes
COPY package*.json ./
# Instala las dependencias del proyecto
RUN npm install
# Copia el resto del código de la aplicación
COPY . .
# Expone el puerto 3000 del contenedor
EXPOSE 3000
# Comando para iniciar la aplicación cuando se ejecute el contenedor
CMD ["node", "server.js"]
Pasos para construir una imagen con un Dockerfile:
- Crea un archivo llamado
Dockerfile
(sin extensión) en la raíz de tu proyecto. - Define las instrucciones paso a paso.
- Desde la terminal en el mismo directorio donde está el
Dockerfile
, ejecuta el comando: Bashdocker build -t mi-app-web:1.0 .
-t mi-app-web:1.0
: Asigna una etiqueta (tag) a la imagen (mi-app-web
) y una versión (1.0
)..
: Indica que el contexto de construcción (los archivos a copiar) está en el directorio actual.
¿Qué es una imagen de Docker y cómo se relaciona con un contenedor?
- Imagen de Docker: Es una plantilla de solo lectura que contiene un sistema de archivos empaquetado, junto con las instrucciones para crear un contenedor. Las imágenes son como las «clases» en la programación orientada a objetos. Son inmutables una vez creadas y se almacenan en registros (como Docker Hub).
- Ejemplo:
ubuntu
,nginx:latest
,mi-app-web:1.0
- Ejemplo:
- Contenedor de Docker: Es una instancia ejecutable de una imagen de Docker. Piensa en los contenedores como los «objetos» o las «instancias» de una clase (la imagen). Un contenedor es una unidad aislada y portable que tiene su propio sistema de archivos (basado en la imagen), procesos, espacio de red y más.
- Puedes iniciar, detener, reiniciar, eliminar múltiples contenedores a partir de la misma imagen. Cada uno funcionará de forma aislada.
Relación: Una imagen es el «molde» o «blueprint», y un contenedor es lo que se «crea» o «instancia» a partir de ese molde.

Usos Generales de Docker
Docker es increíblemente versátil. Aquí algunos de sus usos más comunes:
- Desarrollo Local Consistente: Los desarrolladores pueden replicar el entorno de producción en sus máquinas locales, eliminando el clásico problema de «funciona en mi máquina».
- Integración Continua / Entrega Continua (CI/CD): Dockerfiles pueden ser parte de los pipelines de CI/CD para construir imágenes consistentes en cada commit, y luego desplegar esas mismas imágenes a entornos de prueba o producción.
- Microservicios: Facilita la creación y gestión de arquitecturas de microservicios, donde cada servicio se ejecuta en su propio contenedor aislado.
- Despliegue de Aplicaciones: Permite desplegar aplicaciones de forma rápida y fiable en cualquier infraestructura que soporte Docker (servidores locales, VMs, la nube).
- Aislamiento de Aplicaciones: Se utiliza para ejecutar múltiples aplicaciones en un mismo servidor sin que interfieran entre sí.
- Testing: Crea entornos de prueba limpios y desechables para ejecutar pruebas automatizadas.
- Contenedorización de Bases de Datos: Permite ejecutar instancias de bases de datos (PostgreSQL, MySQL, Redis) en contenedores, facilitando su gestión y aislamiento.
- Educación y Demos: Proporciona entornos listos para usar para demostraciones o cursos sin necesidad de configuraciones complejas.
Características de Docker
Las principales características que hacen de Docker una herramienta tan poderosa son:
- Portabilidad: Una imagen Docker construida una vez puede ejecutarse en cualquier sistema que tenga el Docker Engine instalado, independientemente del sistema operativo subyacente (Linux, Windows, macOS). Esto es el «construye una vez, ejecuta en cualquier lugar».
- Aislamiento: Los contenedores están aislados entre sí y del sistema host. Cada contenedor tiene su propio sistema de archivos, procesos, red y espacio de PID. Esto garantiza que las aplicaciones no interfieran entre sí.
- Consistencia del Entorno: Al empaquetar la aplicación y todas sus dependencias, Docker garantiza que el entorno de ejecución sea idéntico en desarrollo, pruebas y producción, eliminando los errores relacionados con las diferencias de entorno.
- Ligereza: A diferencia de las VMs, los contenedores comparten el kernel del sistema operativo host, lo que los hace significativamente más pequeños en tamaño y más rápidos en su inicio.
- Eficiencia de Recursos: Debido a su ligereza, los contenedores permiten una mayor densidad de aplicaciones por servidor en comparación con las VMs, lo que resulta en un mejor aprovechamiento de los recursos del hardware.
- Versionado de Imágenes: Las imágenes se pueden versionar y etiquetar, lo que permite un control preciso sobre las versiones de las aplicaciones y facilita las reversiones.
- Capas (Layering): Las imágenes Docker se construyen a partir de capas. Cada instrucción en un Dockerfile crea una nueva capa. Esto permite el almacenamiento en caché inteligente y la reutilización de capas, haciendo que las construcciones sean más rápidas y el almacenamiento más eficiente.
- Ecosistema Rico: Docker cuenta con un amplio ecosistema de herramientas como Docker Compose (para aplicaciones multicontenedor), Docker Swarm (para orquestación simple), y es la base para orquestadores más complejos como Kubernetes.
Setup Básico de Docker
El setup de Docker es relativamente sencillo y varía ligeramente según el sistema operativo.
¿Cómo se instala Docker en los sistemas operativos más comunes (Windows, macOS, Linux)?
- Windows y macOS:
- La forma más común y recomendada es descargar e instalar Docker Desktop.
- Docker Desktop incluye el Docker Engine, Docker CLI, Docker Compose y Kubernetes (opcional).
- Visita la página oficial de Docker: https://docs.docker.com/desktop/ y descarga la versión para tu sistema operativo.
- Sigue las instrucciones del instalador. En Windows, necesitarás habilitar WSL 2 (Windows Subsystem for Linux 2) para el mejor rendimiento. En macOS, usa la virtualización nativa.
- Linux (Ubuntu/Debian, CentOS/Fedora, etc.):
- Docker se instala directamente a través del gestor de paquetes de tu distribución.Para Ubuntu/Debian (ejemplo):
Bash
# Actualiza el índice de paquetes
sudo apt-get update
# Instala paquetes necesarios para HTTPS
sudo apt-get install ca-certificates curl gnupg
# Añade la clave GPG oficial de Docker
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Añade el repositorio de Docker a Apt sources
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu"
$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Instala Docker Engine, CLI y Containerd
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# (Opcional pero recomendado) Añade tu usuario al grupo docker para ejecutar comandos sin sudo
sudo usermod -aG docker $USER
# Deberás cerrar sesión y volver a iniciarla para que los cambios de grupo surtan efecto
¿Cuál es el flujo de trabajo básico para construir y ejecutar una aplicación simple con Docker?
Aquí tienes un flujo de trabajo típico para una aplicación sencilla (ej. un servidor web Node.js):
- Crea tu Aplicación:
- Crea un archivo
server.js
(o tu aplicación en cualquier lenguaje).
// server.js const http = require('http'); const hostname = '0.0.0.0'; const port = 3000; const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('¡Hola desde Docker!\n'); }); server.listen(port, hostname, () => { console.log(`Servidor corriendo en http://<span class="math-inline">\{hostname\}\:</span>{port}/`); });
- Crea un archivo
package.json
si es una aplicación Node.js.
- Crea un archivo
- Crea un Dockerfile:
- En el mismo directorio, crea el
Dockerfile
(como el ejemplo de Node.js que te di antes).
- En el mismo directorio, crea el
- Construye la Imagen Docker:
- Abre tu terminal en el directorio de tu proyecto.
- Ejecuta el comando para construir la imagen. Esto tomará el
Dockerfile
y creará la imagen. Bashdocker build -t mi-hola-mundo-app:latest .
- Verás una serie de pasos mientras Docker construye cada capa de la imagen.
- Ejecuta el Contenedor:
- Una vez que la imagen esté construida, puedes iniciar un contenedor a partir de ella. Bash
docker run -d -p 8080:3000 --name mi-servidor-web mi-hola-mundo-app:latest
-d
: Ejecuta el contenedor en modo «detached» (en segundo plano).-p 8080:3000
: Mapea el puerto 8080 de tu máquina local al puerto 3000 del contenedor (donde tu app Node.js está escuchando).--name mi-servidor-web
: Asigna un nombre amigable al contenedor para que sea fácil de identificar.mi-hola-mundo-app:latest
: El nombre y la etiqueta de la imagen que quieres ejecutar.
- Una vez que la imagen esté construida, puedes iniciar un contenedor a partir de ella. Bash
- Verifica la Aplicación:
- Abre tu navegador y ve a
http://localhost:8080
. Deberías ver el mensaje «¡Hola desde Docker!». - Puedes ver tus contenedores en ejecución con
docker ps
. - Para detener el contenedor:
docker stop mi-servidor-web
. - Para eliminar el contenedor (después de detenerlo):
docker rm mi-servidor-web
. - Para eliminar la imagen:
docker rmi mi-hola-mundo-app:latest
.
- Abre tu navegador y ve a
Este flujo de trabajo básico te permite encapsular cualquier aplicación y ejecutarla de forma consistente en cualquier lugar, lo que constituye la esencia del poder de Docker.
Docker ha revolucionado la forma en que empaquetamos, distribuimos y ejecutamos aplicaciones. Es una herramienta indispensable en el arsenal de cualquier desarrollador o ingeniero DevOps. Sin embargo, más allá de los comandos docker run
, docker build
y docker push
que todos conocemos, Docker esconde un sinfín de herramientas y funciones avanzadas que pueden llevar tu eficiencia y la robustez de tus contenedores a un nivel completamente nuevo.
Prepárate para bucear en las profundidades de Docker y descubrir funcionalidades que pocos utilizan, pero que te harán la vida mucho más fácil.
1. docker system prune
– La Limpieza Profunda del Contenedor
Con el tiempo, Docker puede acumular una gran cantidad de «basura» en tu sistema: imágenes no utilizadas, contenedores detenidos, volúmenes huérfanos y redes no usadas. docker system prune
es tu mejor amigo para liberar espacio.
- ¿Qué hace? Elimina todos los contenedores detenidos, todas las redes no utilizadas, todas las imágenes colgantes (sin etiquetar) y opcionalmente todos los volúmenes no utilizados.
- Ejemplo: Bash
# Limpia contenedores detenidos, redes no usadas e imágenes dangling docker system prune # Limpia TODO lo anterior Y volúmenes no usados (¡con precaución!) docker system prune --volumes # Limpia todo sin pedir confirmación (¡MUY peligroso, usar con extremo cuidado!) docker system prune -a --volumes --force
- Beneficio: Evita que tu disco duro se llene innecesariamente y mejora la organización de tu entorno Docker.
2. docker cp
– Copia Directa Hacia y Desde Contenedores
Necesitas copiar un archivo de tu máquina local a un contenedor en ejecución, o viceversa, sin montar volúmenes permanentes. docker cp
es la solución.
- ¿Qué hace? Copia archivos o directorios entre un contenedor y el sistema de archivos local.
- Ejemplo: Bash
# Copiar archivo local a un contenedor docker cp ./mi_archivo_local.txt mi_contenedor:/app/destino.txt # Copiar archivo de un contenedor a la máquina local docker cp mi_contenedor:/app/logs/error.log ./errores.log # Copiar un directorio entero docker cp ./mi_directorio_local mi_contenedor:/app/data
- Beneficio: Depuración rápida, inyección de configuraciones temporales o extracción de logs sin modificar el
Dockerfile
o la configuración de volumen.
3. docker diff
– ¿Qué ha Cambiado en tu Contenedor?
¿Un contenedor se comporta de forma extraña y sospechas que algo cambió internamente? docker diff
te muestra las modificaciones realizadas dentro del sistema de archivos de un contenedor en ejecución.
- ¿Qué hace? Muestra las diferencias (cambios, adiciones, eliminaciones) en el sistema de archivos de un contenedor en comparación con su imagen base.
- Ejemplo: Bash
# Primero, inicia un contenedor (ej. Nginx) docker run -d --name mi_nginx nginx:latest # Entra al contenedor y haz un cambio (ej. crea un archivo) docker exec -it mi_nginx bash # Dentro del contenedor: # echo "Hola desde el contenedor" > /usr/share/nginx/html/nuevo_archivo.txt # exit # Ahora, ve las diferencias desde tu máquina local docker diff mi_nginx # Salida esperada: # C /usr/share/nginx/html # A /usr/share/nginx/html/nuevo_archivo.txt
- Beneficio: Ideal para depurar problemas de configuración, entender cómo los scripts de inicio modifican el contenedor, o identificar archivos temporales.
4. docker inspect
– Radiografía Completa de Objetos Docker
Cuando necesitas obtener información detallada sobre un contenedor, imagen, volumen o red en formato JSON, docker inspect
es tu herramienta.
- ¿Qué hace? Devuelve información de bajo nivel sobre objetos Docker.
- Ejemplo: Bash
# Información detallada de un contenedor docker inspect mi_contenedor # Obtener solo la dirección IP de un contenedor docker inspect -f '{{.NetworkSettings.IPAddress}}' mi_contenedor # Información de una imagen docker inspect nginx:latest
- Beneficio: Esencial para scripts de automatización, depuración de red, y obtener metadatos específicos para tus flujos de trabajo.
5. docker history
– Rastrea el Origen de tu Imagen
¿Te preguntas cómo se construyó una imagen Docker específica? docker history
te muestra la secuencia de capas y los comandos que se usaron para crear cada una.
- ¿Qué hace? Muestra el historial de una imagen.
- Ejemplo: Bash
docker history nginx:latest
- Beneficio: Ideal para entender cómo se construyen las imágenes base, optimizar el tamaño de tus propias imágenes y depurar problemas de construcción.
6. docker events
– Monitoreando el Ciclo de Vida de Docker
docker events
te permite ver en tiempo real los eventos que ocurren en tu demonio Docker, como el inicio/parada de contenedores, la creación/eliminación de imágenes, etc.
- ¿Qué hace? Obtiene eventos en tiempo real del servidor.
- Ejemplo: Bash
docker events # En otra terminal, inicia un contenedor: docker run -d --name prueba busybox sleep 5 # Verás eventos como "create", "start", "die" en la terminal de 'docker events'.
- Beneficio: Monitoreo en tiempo real para sistemas automatizados, scripts de respuesta a eventos, o simplemente para ver la actividad de Docker.
7. docker export
y docker import
– Contenedores como Archivos
A veces, quieres «guardar» el estado de un contenedor como un archivo comprimido para moverlo o archivarlo, y luego «cargarlo» de nuevo.
docker export
: Exporta el sistema de archivos de un contenedor como un archivotar
. Bashdocker export mi_contenedor > mi_contenedor.tar
docker import
: Crea una nueva imagen a partir de un archivotarball
o de una URL. Bashcat mi_contenedor.tar | docker import - mi_nueva_imagen:latest
- Beneficio: Útil para crear imágenes base rápidamente a partir de contenedores modificados (aunque
docker commit
es más común), o para transferir el estado de un contenedor.
8. docker exec
con tty
y stdin
(ya familiar, pero su poder)
Mientras que docker exec -it
es común para entrar a un shell, entender que -i
(interactive) y -t
(tty) pueden usarse de forma independiente abre más posibilidades.
docker exec -i
: Permite enviar datos a la entrada estándar del proceso.docker exec -t
: Asigna un TTY, lo que es necesario para la salida de un shell interactivo.- Ejemplo: Bash
# Enviar un comando simple a un proceso en el contenedor sin un shell interactivo docker exec -i mi_contenedor bash -c "echo 'Hola' > /tmp/saludo.txt" # Iniciar un proceso que interactúa con stdin/stdout, pero sin TTY si no lo necesitas docker exec -i mi_contenedor cat > /tmp/entrada.txt <<EOF Linea 1 Linea 2 EOF
- Beneficio: Mayor control sobre la ejecución de comandos dentro de contenedores para automatización o scripts.
9. Redes Personalizadas Avanzadas (docker network create
)
Más allá de las redes bridge
o host
predeterminadas, crear tus propias redes te da un control granular sobre la comunicación entre contenedores.
- ¿Qué hace? Crea redes personalizadas (bridge, overlay, macvlan) para tus contenedores.
- Ejemplo: Bash
docker network create --driver bridge mi_red_app docker run -d --name db --network mi_red_app postgres:latest docker run -d --name api --network mi_red_app mi_api_image:latest
- Beneficio: Aislamiento de servicios, resolución de nombres simplificada (los contenedores en la misma red se encuentran por nombre), y preparación para entornos de clúster.
10. docker attach
– Conectarse a la Salida Estándar de un Proceso Principal
A diferencia de docker exec
, que inicia un nuevo proceso, docker attach
te conecta al proceso principal que el contenedor inició.
- ¿Qué hace? Adjunta la entrada/salida estándar y la salida de errores estándar a un contenedor en ejecución.
- Ejemplo: Bash
# Inicia un contenedor simple que imprime algo en un bucle docker run -d --name mi_logger busybox sh -c "while true; do echo 'Log: $(date)'; sleep 1; done" # Adjúntate a su salida docker attach mi_logger # Verás los logs en tiempo real. Para salir, usa Ctrl+C (si el proceso lo permite) o Ctrl+P, Ctrl+Q para desadjuntar.
- Beneficio: Útil para monitorear la salida de un proceso de larga duración o para interactuar con aplicaciones que no exponen un shell.
Conclusión
Docker es un universo en sí mismo. Dominar estos «códigos secretos» y funcionalidades menos exploradas no solo te hará un usuario más avanzado, sino que también te permitirá construir, depurar y gestionar tus aplicaciones contenedorizadas con una eficiencia y profesionalismo que pocos alcanzan. ¡Anímate a ir más allá de lo básico y desbloquea el verdadero poder de Docker!