Docker ha pasado de ser una curiosidad para ingenieros de sistemas a una herramienta indispensable para cualquier persona que trabaje con software. Si alguna vez has oído eso de "en mi máquina funciona" y has sentido escalofríos, Docker es exactamente lo que necesitas.

En esta guía práctica vamos a ver qué es Docker, por qué deberías usarlo y, sobre todo, cómo empezar a usarlo desde cero con ejemplos que puedas probar tú mismo.


¿Qué es Docker y por qué debería importarte?

Docker es una herramienta que permite empaquetar una aplicación con todo lo que necesita para funcionar (librerías, dependencias, configuración) en un objeto llamado contenedor. El contenedor se puede ejecutar en cualquier máquina que tenga Docker instalado, independientemente de lo que haya instalado en ella.

Piénsalo como una caja preconfigurada que contiene tu aplicación y todo su entorno. No importa si la abres en Windows, macOS o Linux: dentro de la caja, la aplicación ve siempre el mismo sistema de archivos, las mismas variables de entorno y las mismas versiones de librerías.

¿Por qué es útil?

  • Fin del "en mi máquina funciona": si tu aplicación funciona en un contenedor, funcionará igual en desarrollo, en pruebas y en producción.
  • Aislamiento limpio: cada contenedor tiene su propio sistema de archivos, procesos y red. Puedes tener dos aplicaciones que necesiten versiones distintas de Python sin conflictos.
  • Ligero: a diferencia de las máquinas virtuales, los contenedores comparten el kernel del sistema anfitrión. No arrancan un sistema operativo completo, solo la aplicación y sus dependencias.

Conceptos básicos: imagen vs contenedor

Antes de meter mano, conviene tener claros dos conceptos:

Concepto Qué es
Imagen La receta o plantilla. Un archivo inmutable que contiene todo lo necesario para ejecutar una aplicación.
Contenedor La instancia en ejecución de una imagen. Puedes tener múltiples contenedores de la misma imagen, cada uno con su propio estado.

La analogía con la programación orientada a objetos funciona bien: una imagen es una clase, un contenedor es una instancia de esa clase.


Paso 1: Instalar Docker

Docker está disponible para Linux, macOS y Windows.

Linux (Debian/Ubuntu):

ice-tech
sudo apt update
sudo apt install docker.io
sudo systemctl start docker
sudo systemctl enable docker

Windows y macOS: descarga Docker Desktop e instálalo. En Windows necesitarás tener WSL2 configurado (Docker Desktop te guía en el proceso).

Para verificar que Docker se ha instalado correctamente:

ice-tech
docker --version

Si ves algo como Docker version 27.x.x, estás listo.


Paso 2: Tu primer contenedor

Abre un terminal y ejecuta:

ice-tech
docker run hello-world

Este comando hace varias cosas:
1. Docker busca la imagen hello-world en tu máquina
2. Como no la encuentra, la descarga de Docker Hub (el repositorio oficial de imágenes)
3. Crea un contenedor a partir de esa imagen y lo ejecuta
4. El contenedor imprime un mensaje y se detiene

Has ejecutado tu primer contenedor. No ha pasado nada espectacular, pero el mecanismo es el mismo que usarás para ejecutar cualquier aplicación.


Paso 3: Ejecutar aplicaciones reales en contenedores

Vamos a hacer algo más útil. Vamos a ejecutar un servidor web Nginx:

ice-tech
docker run -d -p 8080:80 --name mi-nginx nginx

Desglose del comando:
- -d → modo "detached": el contenedor se ejecuta en segundo plano
- -p 8080:80 → mapea el puerto 80 del contenedor al puerto 8080 de tu máquina
- --name mi-nginx → le damos un nombre para referirnos a él después
- nginx → el nombre de la imagen en Docker Hub

Abre tu navegador en http://localhost:8080. Verás la página de bienvenida de Nginx.

Para ver los contenedores en ejecución:

ice-tech
docker ps

Para detener el contenedor:

ice-tech
docker stop mi-nginx

Para eliminarlo:

ice-tech
docker rm mi-nginx

Paso 4: Gestionar imágenes y contenedores

Aquí tienes los comandos esenciales del día a día:

ice-tech
# Listar imágenes descargadas
docker images

# Listar contenedores en ejecución
docker ps

# Listar todos los contenedores (incluyendo los detenidos)
docker ps -a

# Ver logs de un contenedor en tiempo real
docker logs -f mi-nginx

# Ejecutar un comando dentro de un contenedor en ejecución
docker exec -it mi-nginx bash

# Eliminar una imagen
docker rmi nginx

# Eliminar todos los contenedores detenidos
docker container prune

Paso 5: Crear tu propia imagen con un Dockerfile

Hasta ahora hemos usado imágenes creadas por otros. Para contenerizar tu propia aplicación necesitas crear un Dockerfile, que es el archivo de instrucciones para construir tu imagen.

Vamos a crear una imagen para una aplicación simple en Python que muestra la hora actual.

Crea un archivo app.py:

ice-tech
from http.server import HTTPServer, BaseHTTPRequestHandler
from datetime import datetime

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/plain; charset=utf-8')
        self.end_headers()
        now = datetime.now().strftime('%d/%m/%Y %H:%M:%S')
        self.wfile.write(f'🕒 Hora actual: {now}\n'.encode('utf-8'))

HTTPServer(('0.0.0.0', 8080), Handler).serve_forever()

Ahora crea un archivo llamado Dockerfile en el mismo directorio:

ice-tech
# Imagen base ligera de Python
FROM python:3.11-alpine

# Directorio de trabajo dentro del contenedor
WORKDIR /app

# Copiar nuestro código al contenedor
COPY app.py .

# Puerto que expone la aplicación
EXPOSE 8080

# Comando que se ejecuta al iniciar el contenedor
CMD ["python", "app.py"]

Construye la imagen:

ice-tech
docker build -t hora-actual .

Ejecútala:

ice-tech
docker run -d -p 8080:8080 --name mi-hora hora-actual

Visita http://localhost:8080 y verás la hora actual. Acabas de contenerizar tu primera aplicación.


Paso 6: Persistir datos con volúmenes

Los contenedores son efímeros: cuando los eliminas, todos los datos generados dentro se pierden. Para datos que deben persistir (bases de datos, archivos subidos, logs), se usan volúmenes.

Ejecuta una base de datos PostgreSQL con un volumen persistente:

ice-tech
docker run -d \
  -p 5432:5432 \
  -e POSTGRES_PASSWORD=mi_password \
  -v pgdata:/var/lib/postgresql/data \
  --name mi-postgres \
  postgres:16

El flag -v pgdata:/var/lib/postgresql/data crea un volumen llamado pgdata y lo monta en el directorio de datos de PostgreSQL. Aunque elimines y recrees el contenedor, los datos se conservan.

Para ver y gestionar volúmenes:

ice-tech
docker volume ls
docker volume inspect pgdata

Paso 7: Orquestar múltiples contenedores con Docker Compose

Cuando tu aplicación necesita varios servicios (una base de datos, un backend, un frontend), gestionarlos uno a uno con docker run se vuelve tedioso. Docker Compose te permite definir todos los servicios en un archivo YAML y levantarlos con un solo comando.

Crea un archivo compose.yaml:

ice-tech
services:
  web:
    build: .
    ports:
      - "8080:8080"
    depends_on:
      - db

  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: mi_password
      POSTGRES_DB: miapp
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

Levanta todo con un solo comando:

ice-tech
docker compose up -d

Para ver los logs de todos los servicios a la vez:

ice-tech
docker compose logs -f

Para detener y limpiar:

ice-tech
docker compose down

Docker Compose es probablemente la herramienta que más usarás a partir de ahora. Te permite tener entornos de desarrollo completos con una sola instrucción y compartirlos con tu equipo.


Resumen y próximos pasos

En esta guía has aprendido:

  • Qué son los contenedores y por qué resuelven el problema del "en mi máquina funciona"
  • La diferencia entre imagen y contenedor
  • Comandos esenciales: docker run, docker ps, docker stop, docker exec
  • Cómo crear tu propia imagen con un Dockerfile
  • Cómo persistir datos con volúmenes
  • Cómo orquestar servicios con Docker Compose

¿Qué más puedes explorar?

  • Docker Hub tiene miles de imágenes listas para usar: bases de datos, servidores web, lenguajes de programación
  • Las redes de Docker te permiten aislar o conectar contenedores entre sí de forma flexible
  • Kubernetes es el siguiente escalón si necesitas gestionar decenas o cientos de contenedores en producción

Docker no es difícil: son cuatro conceptos bien entendidos y el resto es práctica. Empieza por contenerizar una aplicación pequeña y ve aumentando la complejidad poco a poco. En un par de semanas te preguntarás cómo trabajabas sin él.