Lo que vas a construir
Vas a instalar Docker y crear tu primer contenedor: una app Node.js empaquetada que funciona igual en cualquier computadora. Aprenderás a correr contenedores de Ubuntu, bases de datos como PostgreSQL, y a usar volúmenes para no perder datos. Al terminar, tendrás una app Dockerizada con su Dockerfile, docker-compose.yml, y la capacidad de levantar servicios con un comando. Es la base para trabajar en equipos donde "en mi máquina funciona" ya no será un problema.
Paso 1: Instalar Docker
| Sistema | Instalación |
|---|---|
| macOS | Docker Desktop |
| Windows | Docker Desktop |
| Linux | `curl -fsSL https://get.docker.com |
Verifica:
docker --version
docker run hello-world
⚠️ Windows: Necesitas WSL2 habilitado. Docker Desktop te guía en la instalación.
Paso 2: Tu primer contenedor
# Descarga y corre Ubuntu en segundos
docker run -it ubuntu bash
# Ahora estás DENTRO del contenedor
cat /etc/os-release # Verás "Ubuntu"
apt update # Funciona como Linux real
exit # Sales del contenedor
¿Qué pasó? Docker descargó una imagen de Ubuntu (~30MB, no 4GB) y la ejecutó aislada de tu sistema.
Paso 3: Corre servicios útiles
Docker brilla cuando necesitas bases de datos o servicios sin instalar nada permanente:
# PostgreSQL listo en 10 segundos
docker run -d --name mi-postgres \
-e POSTGRES_PASSWORD=secreto \
-p 5432:5432 \
postgres:16-alpine
# Redis para caché
docker run -d --name mi-redis -p 6379:6379 redis:alpine
# Adminer (interfaz web para bases de datos)
docker run -d --name adminer -p 8080:8080 adminer
Abre http://localhost:8080 para ver Adminer funcionando.
⚠️ PROBLEMA: Si haces docker rm mi-postgres, pierdes TODOS los datos. Sigue leyendo para solucionarlo.
Paso 4: Volúmenes (Datos Persistentes)
El problema más común de principiantes: Crean una base de datos, guardan datos, eliminan el contenedor... y pierden todo.
¿Por qué pasa esto?
SIN VOLUMEN:
┌─────────────────────────┐
│ Contenedor │
│ ┌─────────────────┐ │
│ │ Base de datos │ │ ← Los datos viven DENTRO
│ │ (tus datos) │ │ del contenedor
│ └─────────────────┘ │
└─────────────────────────┘
↓
docker rm postgres
↓
💀 DATOS PERDIDOS
CON VOLUMEN:
┌─────────────────────────┐ ┌─────────────────┐
│ Contenedor │ │ Volumen │
│ ┌─────────────────┐ │ ──── │ (tu disco) │
│ │ Base de datos │────│──────│ tus datos │
│ └─────────────────┘ │ └─────────────────┘
└─────────────────────────┘ ↓
↓ Los datos están
docker rm postgres FUERA del contenedor
↓ ↓
Contenedor eliminado ✅ DATOS SEGUROS
Crear PostgreSQL con volumen persistente
# Crea un volumen con nombre
docker volume create postgres_data
# Corre PostgreSQL usando ese volumen
docker run -d --name mi-postgres \
-e POSTGRES_PASSWORD=secreto \
-e POSTGRES_USER=dev \
-e POSTGRES_DB=miapp \
-p 5432:5432 \
-v postgres_data:/var/lib/postgresql/data \
postgres:16-alpine
La magia está en -v postgres_data:/var/lib/postgresql/data:
postgres_data= nombre del volumen en tu máquina/var/lib/postgresql/data= donde Postgres guarda datos dentro del contenedor
Prueba que funciona
# Conecta y crea una tabla
docker exec -it mi-postgres psql -U dev -d miapp -c "CREATE TABLE test (id INT);"
docker exec -it mi-postgres psql -U dev -d miapp -c "INSERT INTO test VALUES (1), (2), (3);"
# Elimina el contenedor
docker stop mi-postgres && docker rm mi-postgres
# Crea uno nuevo con el MISMO volumen
docker run -d --name mi-postgres \
-e POSTGRES_PASSWORD=secreto \
-e POSTGRES_USER=dev \
-e POSTGRES_DB=miapp \
-p 5432:5432 \
-v postgres_data:/var/lib/postgresql/data \
postgres:16-alpine
# Verifica que los datos siguen ahí
docker exec -it mi-postgres psql -U dev -d miapp -c "SELECT * FROM test;"
# Resultado: 1, 2, 3 ✅
Comandos de volúmenes
| Comando | Qué hace |
|---|---|
docker volume create nombre | Crea un volumen |
docker volume ls | Lista todos los volúmenes |
docker volume inspect nombre | Ver detalles (ubicación real) |
docker volume rm nombre | Elimina volumen (¡y sus datos!) |
docker volume prune | Elimina volúmenes no usados |
Tipos de montaje
| Tipo | Sintaxis | Uso |
|---|---|---|
| Named Volume | -v mi_volumen:/data | Producción, bases de datos |
| Bind Mount | -v ./local:/data | Desarrollo, ver cambios en vivo |
| Anonymous | -v /data | Temporal, no recomendado |
Ejemplo de Bind Mount para desarrollo:
# Tu código local se sincroniza con el contenedor
docker run -d --name mi-app \
-v $(pwd):/app \
-p 3000:3000 \
node:20-alpine npm start
Cambias un archivo → el contenedor lo ve inmediatamente.
Paso 5: Crea tu propia imagen
Ahora que entiendes contenedores y volúmenes, crea tu propia imagen.
Crea una carpeta docker-hello con estos 3 archivos:
Dockerfile:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["node", "index.js"]
index.js:
console.log("¡Hola desde Docker! 🐳");
console.log("Fecha:", new Date().toISOString());
console.log("Node version:", process.version);
package.json:
{ "name": "docker-hello", "version": "1.0.0" }
Construye y ejecuta:
docker build -t mi-app .
docker run mi-app
Paso 6: Instala Portainer (Gestión Visual)
Portainer es una interfaz web para Docker. Perfecto para principiantes:
# Crea un volumen para persistir datos
docker volume create portainer_data
# Instala Portainer
docker run -d -p 9000:9000 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
Abre http://localhost:9000 y crea tu usuario admin.
¿Qué puedes hacer con Portainer?
- Ver todos tus contenedores en una tabla
- Iniciar/detener/eliminar con un click
- Ver logs en tiempo real
- Crear contenedores sin comandos
- Gestionar imágenes, volúmenes, redes
💡 Tip: Deja Portainer corriendo siempre. Es como el "Finder" o "Explorer" pero para Docker.
🛠️ Herramientas de gestión
| Herramienta | Tipo | Ideal para |
|---|---|---|
| Portainer | UI local/servidor | Gestionar Docker visualmente |
| Docker Desktop | App desktop | Mac/Windows, incluye UI básica |
| Lazydocker | TUI terminal | Fans de la terminal |
Para deploy en producción
| Herramienta | Descripción | Costo |
|---|---|---|
| EasyPanel | Deploy como Heroku, pero en tu VPS | Gratis self-hosted |
| Coolify | Open source, muy completo | Gratis self-hosted |
| Dokku | Mini-Heroku en tu servidor | Gratis |
| CapRover | PaaS simple con Let's Encrypt | Gratis |
🎯 Recomendación para principiantes: Usa Portainer para aprender, luego EasyPanel o Coolify cuando quieras deploy fácil.
Comandos esenciales
| Comando | Qué hace |
|---|---|
docker run -d nombre | Corre en background |
docker ps | Lista contenedores activos |
docker ps -a | Lista TODOS (incluso detenidos) |
docker logs nombre | Ver logs |
docker logs -f nombre | Logs en tiempo real |
docker stop nombre | Detener contenedor |
docker rm nombre | Eliminar contenedor |
docker images | Lista imágenes descargadas |
docker rmi nombre | Eliminar imagen |
docker system prune | Limpia todo lo no usado |
Si algo falló
| Error | Causa | Solución |
|---|---|---|
daemon not running | Docker no está corriendo | Abre Docker Desktop |
permission denied | Sin permisos | Linux: sudo usermod -aG docker $USER y reinicia sesión |
port already in use | Puerto ocupado | Cambia el puerto: -p 9001:9000 |
no space left | Disco lleno de imágenes | docker system prune -a |
cannot connect a localhost | Contenedor no expone puerto | Agrega -p puerto:puerto |
Lo que aprendiste
✅ Instalar Docker y verificar que funcione ✅ Correr contenedores pre-hechos (Ubuntu, Postgres, Redis) ✅ Usar volúmenes para no perder datos (el error #1 de principiantes) ✅ Crear tu propia imagen con Dockerfile ✅ Usar Portainer para gestión visual ✅ Comandos esenciales para el día a día
Próximos pasos
→ Consumir una API JSON — Conecta tu app con datos reales → Deploy con Docker — Lleva tu contenedor a producción → Docker Básico (teoría) — Entiende containers vs VMs