Los contenedores han cambiado la forma en que desarrollamos, empaquetamos y desplegamos software. Si estudias sistemas o redes, entender Docker hoy es tan esencial como saber configurar una IP.
¿Qué es un contenedor?
Un contenedor es una unidad de software que empaqueta el código de una aplicación junto con todas sus dependencias — librerías, variables de entorno, archivos de configuración — para que se ejecute de forma idéntica en cualquier entorno: tu laptop, un servidor de pruebas o la nube.
A diferencia de una máquina virtual, un contenedor no incluye un sistema operativo completo. Comparte el kernel del sistema anfitrión, lo que lo hace mucho más ligero y rápido de iniciar.
Contenedores vs Máquinas Virtuales
Esta es la comparación que más confunde al principio. Aquí la diferencia clave:
| Característica | Máquina Virtual | Contenedor Docker |
|---|---|---|
| Tamaño | Gigabytes (SO completo) | Megabytes (solo la app) |
| Inicio | Minutos | Segundos (o menos) |
| Aislamiento | Total (hipervisor) | Proceso (kernel compartido) |
| Recursos | Alto consumo | Muy eficiente |
| Portabilidad | Media | Muy alta |
Esto no significa que los contenedores reemplacen a las VMs en todos los casos. Para aislar sistemas operativos completos o correr aplicaciones con dependencias de kernel muy específicas, las VMs siguen siendo la opción correcta.
Arquitectura de Docker
Docker sigue una arquitectura cliente-servidor con tres componentes principales:
- Docker Daemon (
dockerd) — el proceso en segundo plano que gestiona imágenes, contenedores, redes y volúmenes. - Docker CLI — el cliente de línea de comandos que envía instrucciones al daemon.
- Docker Hub / Registry — repositorio donde se almacenan y distribuyen las imágenes.
El flujo básico es: tú escribes un Dockerfile → Docker construye una imagen → a partir de esa imagen se crean uno o más contenedores en ejecución.
Comandos esenciales
Antes de escribir tu propio Dockerfile, necesitas dominar los comandos básicos del CLI:
# Descargar una imagen desde Docker Hub
docker pull nginx
# Listar imágenes descargadas
docker images
# Ejecutar un contenedor (modo interactivo)
docker run -it ubuntu bash
# Ejecutar en background y mapear puertos
docker run -d -p 8080:80 --name mi-nginx nginx
# Ver contenedores en ejecución
docker ps
# Ver todos los contenedores (incluidos detenidos)
docker ps -a
# Detener un contenedor
docker stop mi-nginx
# Eliminar un contenedor
docker rm mi-nginx
# Eliminar una imagen
docker rmi nginx
docker volume) o bind mounts.
Tu primer Dockerfile
Un Dockerfile es un archivo de texto con instrucciones para construir una imagen. Cada instrucción crea una capa en la imagen final.
Ejemplo: imagen de una app PHP simple:
# Imagen base oficial de PHP con Apache
FROM php:8.2-apache
# Instalar extensión PDO para MySQL
RUN docker-php-ext-install pdo pdo_mysql
# Copiar el código de la app al directorio web de Apache
COPY . /var/www/html/
# Establecer permisos
RUN chown -R www-data:www-data /var/www/html
# Exponer el puerto 80
EXPOSE 80
Para construir y ejecutar esta imagen:
# Construir la imagen con tag "mi-app"
docker build -t mi-app .
# Ejecutar el contenedor en el puerto 8080
docker run -d -p 8080:80 mi-app
Docker Compose: orquesta múltiples servicios
La mayoría de las aplicaciones reales necesitan más de un servicio: una app web, una base de datos, un caché. Docker Compose permite definir y levantar todos en un solo archivo docker-compose.yml.
Ejemplo: app PHP + MariaDB + phpMyAdmin:
version: '3.9'
services:
web:
build: .
ports:
- "8080:80"
volumes:
- .:/var/www/html
depends_on:
- db
db:
image: mariadb:10.11
environment:
MYSQL_ROOT_PASSWORD: secreto
MYSQL_DATABASE: solutions
MYSQL_USER: dev
MYSQL_PASSWORD: dev123
volumes:
- db_data:/var/lib/mysql
phpmyadmin:
image: phpmyadmin
ports:
- "8081:80"
environment:
PMA_HOST: db
volumes:
db_data:
Con un solo comando levantas todo el stack:
# Levantar todos los servicios en background
docker compose up -d
# Ver logs de todos los servicios
docker compose logs -f
# Detener y eliminar contenedores
docker compose down
docker compose down -v con cuidado — el flag -v también elimina los volúmenes y perderás los datos de la base de datos.
Redes en Docker
Docker crea automáticamente una red interna para los contenedores de un mismo Compose. Los servicios se comunican entre sí usando su nombre como hostname — en el ejemplo anterior, la app web se conecta a MariaDB simplemente usando db como host.
Tipos de red más comunes:
- bridge (por defecto) — red privada interna, los contenedores se ven entre sí.
- host — el contenedor usa directamente la red del host, sin aislamiento.
- none — sin red, aislamiento total.
Conclusión
Docker resolvió uno de los problemas clásicos del desarrollo: "en mi máquina funciona". Con contenedores, el entorno de desarrollo, pruebas y producción es el mismo. Para un estudiante de sistemas, dominar Docker abre puertas a DevOps, CI/CD, Kubernetes y arquitecturas modernas de microservicios.
En los siguientes artículos veremos cómo usar Docker para montar laboratorios de redes con GNS3, cómo integrar Packet Tracer en un flujo de desarrollo, y cómo construir pipelines de CI/CD desde cero.
"La diferencia entre un desarrollador junior y uno senior no es el lenguaje que conocen — es que el senior sabe cómo desplegar lo que construye."