Qué es un contenedor
Uno contenedor es una caja cerrada que lleva tu programa junto con todo lo que necesita para funcionar: el código, las bibliotecas, la versión correcta del lenguaje e incluso una pequeña parte del sistema operativo. Envías esa caja a cualquier computadora y funciona exactamente igual. Sin «instalar dependencias», sin «configurar el entorno», sin sorpresas.
🧠 Analogía: la maleta de viaje completa
Imagina que vas a viajar y no confías en encontrar nada en el destino. Entonces preparas una maleta con TODO: ropa, cepillo, almohada, hasta un adaptador de corriente. Dondequiera que llegues, abres la maleta y tienes exactamente las mismas comodidades que en casa. El contenedor es esa maleta para tu programa.
- •La maleta: el contenedor (la caja cerrada)
- •Qué incluye: tu aplicación, las bibliotecas, la versión correcta de todo
- •El destino: cualquier computadora con Docker (tu PC, la nube, el servidor)
- •El resultado: se ejecuta igual en todas partes, sin «en mi máquina funciona»
💡 El contenedor no es una máquina virtual
Puedes pensar que es una máquina virtual (VM), pero es mucho más ligera. Una VM carga un sistema operativo completo desde cero (pesa gigas, tarda minutos en arrancar). El contenedor comparte el sistema de la computadora y empaqueta solo lo que tu app necesita. Por eso arranca en segundos y ejecutas decenas de ellos en la misma computadora sin que se trabe.
Instalando Docker
Antes de ejecutar cualquier contenedor, necesitas instalar Docker. En el Windows y Mac instalas Docker Desktop (un programa con ventana). En Linux, instalas Docker Engine directamente desde la terminal. Veamos cómo hacerlo según el sistema.
Windows
Docker Desktop (necesitas tener WSL2 activado)
# 1. Descarga el instalador
docker.com/products/docker-desktop
# 2. Ejecuta el instalador, marca "Usar WSL 2"
Docker Desktop Installer.exe
# 3. Reinicia y abre Docker Desktop
macOS
Docker Desktop (versión Intel o Apple Silicon)
# Opción 1: sitio oficial
Descarga el .dmg y arrástralo a Aplicaciones
# Opción 2: Homebrew (si lo tienes)
$ brew install --cask docker
Linux (Ubuntu/Debian)
Docker Engine, instalado con el script oficial
# Script oficial de instalación
$ curl -fsSL https://get.docker.com | sh
# Ejecutar docker sin sudo (vuelve a iniciar sesión después)
$ sudo usermod -aG docker $USER
👁 Cómo confirmar que se instaló
Abre la terminal y pide la versión. Si aparece un número, está funcionando:
$ docker --version
Docker version 27.3.1, build ce12230
# Verificación más completa (cliente + servidor):
$ docker info
Server Version: 27.3.1
Containers: 0 Images: 0
Si aparece la versión, Docker está instalado y listo. Puedes pasar al siguiente tema y ejecutar tu primer contenedor.
⚠️ Error común
Problema: se ejecuta docker info y aparece "Cannot connect to the Docker daemon".
Solución: Docker está instalado, pero el motor (daemon) no está encendido. En Windows/Mac, abre Docker Desktop y espera a que el ícono se ponga verde. En Linux, ejecuta sudo systemctl start docker.
docker run: Tu primer contenedor
El comando docker run y es el corazón de Docker. Lo hace todo de una vez: descarga la imagen (si no la tienes), crea un container a partir de ella y lo inicia. Pasaremos del "hola mundo" de Docker a ejecutar un servidor de verdad.
docker run hello-world - La prueba
Este comando descarga una imagen diminuta, la ejecuta e imprime un mensaje. Es la forma oficial de confirmar que todo funciona.
$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
Hello from Docker!
This message shows that your installation
appears to be working correctly.
docker run -p - Abriendo la puerta
El contenedor está cerrado. Para acceder desde el navegador a un sitio dentro de él, conectas un puerto tuyo a uno de sus puertos con -p porta-sua:porta-do-container.
# Ejecutar nginx (servidor web) en el puerto 8080
$ docker run -p 8080:80 nginx
# -d = se ejecuta en segundo plano (detached)
$ docker run -d -p 8080:80 nginx
a1b2c3d4e5f6...
# Ahora ábrelo en el navegador:
http://localhost:8080
A la izquierda de : y es el puerto de tu computadora; a la derecha está el puerto dentro del contenedor.
docker ps - Qué está en ejecución
Lista los contenedores que están activos ahora. Con -a también muestra los que ya se detuvieron.
$ docker ps
CONTAINERS ID IMAGE STATUS PORTS
a1b2c3d4e5f6 nginx Up 2 minutes 0.0.0.0:8080->80/tcp
# Detener un contenedor por ID
$ docker stop a1b2c3d4e5f6
# Ver todos, incluso los detenidos
$ docker ps -a
💡 Consejo: no hace falta memorizar el ID completo
El ID del contenedor es un código largo, pero solo necesitas escribir los primeros caracteres (por lo general, 3 o 4 ya son suficientes). En vez de docker stop a1b2c3d4e5f6, basta docker stop a1b2. Docker lo entiende.
✓ Qué HACER
- ✓Usar
-dpara ejecutar servidores en segundo plano - ✓Verificar con
docker pslo que está en línea - ✓Detener los contenedores que ya no usas (libera puertos y memoria)
✗ Qué NO hacer
- ✗Invertir el puerto (
-p 80:8080cuando la app usa 80) - ✗Olvidar los contenedores encendidos y consumiendo recursos
- ✗Usar tu mismo puerto en dos contenedores al mismo tiempo
Imágenes vs. contenedores
Esta es la confusión número 1 de quienes empiezan. La regla es simple: la imagen y el molde (detenida, guardada en el disco) y el contenedor y la instancia en ejecución (activo, en ejecución). A partir de una sola imagen puedes crear tantos contenedores como quieras.
🧠 Analogía: la receta y el pastel
A imagen y es la receta de cocina en un papel: solo describe, no se puede comer. El contenedor y es el pastel horneado de verdad, listo en la mesa. Con una receta puedes hornear todos los pasteles que quieras, todos iguales. ¿Te comiste uno? Haz otro con la misma receta.
- •Imagen (receta): archivo guardado en el disco, no consume memoria
- •Contenedor (pastel): proceso en ejecución, consume CPU y memoria
- •1 imagen -> N contenedores: una receta, varios pasteles
Comandos de IMAGEN
# Listar imágenes en el disco
$ docker images
REPOSITORY TAG SIZE
nginx latest 187MB
# Descargar una imagen
$ docker pull node:20
# Borrar una imagen
$ docker rmi nginx
Comandos de CONTENEDOR
# Listar contenedores en ejecución
$ docker ps
# Detener un contenedor
$ docker stop a1b2
# Borrar un contenedor detenido
$ docker rm a1b2
# Ver sus registros (salida)
$ docker logs a1b2
⚠️ Error común
Problema: intenta docker rmi nginx y aparece "image is being used by running container".
Solución: no puedes borrar la receta mientras haya un pastel sobre la mesa. Detén y elimina primero los contenedores que usan la imagen (docker stop + docker rm), luego elimina la imagen.
images
Listar plantillas
pull
Descargar plantilla
ps
Contenedores activos
rm / rmi
Borrar
Dockerfile: la receta del contenedor
Hasta ahora usaste imágenes listas (nginx, hello-world). Pero ¿y TU programa? Para empaquetar tu código en una imagen, escribes un Dockerfile: un archivo de texto con la receta, línea por línea, para construir la imagen.
📝 Un Dockerfile de ejemplo (app Node)
# parte de una imagen base con Node ya instalado
FROM node:20
# carpeta de trabajo dentro del contenedor
WORKDIR /app
# copia los archivos de tu proyecto adentro
COPY . .
# ejecuta un comando al crear la imagen
RUN npm install
# comando que se ejecuta cuando se inicia el contenedor
CMD ["node", "server.js"]
FROM - por dónde empezar
Toda receta empieza con una imagen base ya preparada (Node, Python, Ubuntu...). No armas todo desde cero, sino que partes de algo que ya existe.
COPY - llevar tu código hacia adentro
Copia archivos de tu computadora dentro de la imagen. El COPY . . lleva toda la carpeta actual a la carpeta de trabajo del contenedor.
RUN - ejecutar en el montaje
Ejecuta un comando mientras se construye la imagen (p. ej., instalar dependencias). El resultado queda guardado en la imagen.
CMD - qué hacer al iniciar
Define el comando que se ejecuta cuando se inicia el contenedor. A diferencia de RUN (montaje), CMD se ejecuta durante la ejecución.
💡 Consejo: RUN x CMD
La confusión más común: RUN sucede cuando tú construye la imagen (una vez, y se congela en la plantilla). CMD sucede cuando tú se ejecuta el contenedor (cada vez que se enciende). Piensa: RUN = hacer la maleta; CMD = lo que haces al llegar a tu destino.
Build y push: del Dockerfile al mundo
Tienes el Dockerfile (la receta). Ahora viene el ciclo final: build convierte la receta en una imagen, run inicia un contenedor de ella, y push envía la imagen a un registry en la nube para que cualquier servidor pueda descargarla y ejecutarla.
Build: crear la imagen
O -t le da un nombre (tag) a la imagen. El punto al final es la carpeta actual (donde está el Dockerfile).
$ docker build -t meu-app .
[+] Building 12.3s
=> [1/4] FROM node:20
=> [4/4] RUN npm install
=> naming to docker.io/library/meu-app
Run: probar localmente
Antes de lanzarla al mundo, ejecuta la imagen que acabas de crear.
$ docker run -p 3000:3000 meu-app
Servidor ejecutándose en el puerto 3000
Push: enviar al registry
El registry es la «nube de imágenes» (Docker Hub es el más común). Inicias sesión, etiquetas la imagen con tu usuario y la envías.
# 1. iniciar sesión en Docker Hub
$ docker login
# 2. marcar con tu usuario
$ docker tag meu-app seuuser/meu-app:1.0
# 3. enviar a la nube
$ docker push seuuser/meu-app:1.0
The push refers to repository [docker.io/seuuser/meu-app]
1.0: pushed
👁 El ciclo completo, de cero al deploy
# 1. escribir la receta (Dockerfile)
# 2. crear la imagen
$ docker build -t seuuser/meu-app:1.0 .
# 3. enviar al registry
$ docker push seuuser/meu-app:1.0
# 4. en el servidor, descargar y ejecutar
$ docker run -d -p 80:3000 seuuser/meu-app:1.0
✓ Qué HACER
- ✓Versionar la etiqueta (
:1.0,:1.1) en lugar de sololatest - ✓Probar con
docker runantes de hacer push - ✓Crear uno
.dockerignorepara no copiar basura
✗ Qué NO hacer
- ✗Poner contraseñas/tokens dentro de la imagen
- ✗Hacer push de una imagen que nunca se ejecutó localmente
- ✗Subir la carpeta
node_modulesdentro de la imagen
🏆 ¡Felicitaciones!
Ya entiendes el ciclo completo de Docker: imagen, container, Dockerfile, build y push. Con esto, tu programa funciona igual en tu PC y en cualquier servidor del mundo. En el próximo módulo, aprenderás a orquestar varios containers a la vez con el Docker Compose.
📚 Resumen del módulo
Siguiente módulo:
4.2 - Docker Compose: orquestar varios contenedores (app + base de datos + caché) con un solo archivo