PTENES
MÓDULO 4.1

🐳 Docker para principiantes

"En mi máquina funciona" es la frase que Docker vino a desterrar. Con él, empaquetas tu programa con todo lo que necesita en una caja que funciona igual en cualquier computadora. Aquí entenderás los contenedores desde cero y ejecutarás el primero.

6
Temas
45
Minutos
Básico
Nivel
Práctico
Tipo
1

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.

IMAGEN (plantilla) 📦 código + libs + runtime + SO docker run CONTAINERS (instancias en ejecución) app #1 app #2 app #3 app #4 app #5 una imagen, muchos contenedores idénticos

🧠 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.

2

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.

W

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.

3

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 -d para ejecutar servidores en segundo plano
  • ✓Verificar con docker ps lo que está en línea
  • ✓Detener los contenedores que ya no usas (libera puertos y memoria)

✗ Qué NO hacer

  • ✗Invertir el puerto (-p 80:8080 cuando la app usa 80)
  • ✗Olvidar los contenedores encendidos y consumiendo recursos
  • ✗Usar tu mismo puerto en dos contenedores al mismo tiempo
4

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

5

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.

6

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.

1

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

2

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

3

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 solo latest
  • ✓Probar con docker run antes de hacer push
  • ✓Crear uno .dockerignore para 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_modules dentro 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

✓
El contenedor es una maleta completa - empaqueta la app y todo lo que necesita; funciona igual en cualquier lugar
✓
docker --version e docker run - instalaste y ejecutaste tu primer contenedor (hello-world, nginx con -p)
✓
La imagen es el molde; el contenedor, la instancia - una imagen genera tantos contenedores como quieras
✓
Dockerfile es la receta - FROM, COPY, RUN, CMD construyen la imagen de tu app
✓
build y push - docker build -t crea la imagen, docker push la envía al registry

Siguiente módulo:

4.2 - Docker Compose: orquestar varios contenedores (app + base de datos + caché) con un solo archivo