Guía Completa de Docker y Docker Compose: Comandos y Mejores Prácticas
Guía Completa de Docker y Docker Compose: Comandos y Mejores Prácticas
Conceptos Fundamentales de Docker
Docker es un sistema de código abierto que facilita el desarrollo, despliegue y ejecución de aplicaciones mediante la contenedorización. Resuelve problemas de compatibilidad al empaquetar una aplicación y sus dependencias en unidades autónomas y portátiles que se ejecutan consistentemente en cualquier entorno.
Componentes Clave
-
Imágenes (Images): Son paquetes ejecutables de software ligeros, autónomos que contienen todo lo necesario para ejecutar una aplicación (código, runtime, bibliotecas, configuraciones). Son la plantilla virtualizada para crear contenedores.
-
Contenedores (Containers): Son la instancia de tiempo de ejecución de una imagen de Docker. Aislan el software de su entorno, permitiendo ejecutar muchos simultáneamente en un host.
-
Docker Hub: Es un servicio proporcionado por Docker para encontrar y compartir imágenes de contenedores.
Comandos CLI de Docker (Básico)
| Tarea | Comando CLI | Descripción |
|---|---|---|
| Imágenes | ||
| Construir una Imagen | docker build -t <nombre_imagen> . | Construye una imagen a partir de un Dockerfile en el directorio actual. |
| Construir sin caché | docker build -t <nombre_imagen> . --no-cache | Fuerza la reconstrucción sin usar la caché. |
| Listar Imágenes | docker images | Muestra todas las imágenes locales. |
| Eliminar una Imagen | docker rmi <nombre_imagen> | Elimina una imagen local. |
| Eliminar Imágenes no usadas | docker image prune | Elimina todas las imágenes no usadas. |
| Publicar en Docker Hub | docker push <usuario>/<nombre_imagen> | Sube una imagen a Docker Hub. |
| Contenedores | ||
| Ejecutar Contenedor (con nombre) | docker run --name <nombre_contenedor> <nombre_imagen> | Crea y ejecuta un contenedor a partir de una imagen. |
| Ejecutar en Segundo Plano | docker run -d <nombre_imagen> | Ejecuta el contenedor en modo detached (segundo plano). |
| Ejecutar y Publicar Puertos | docker run -p <puerto_host>:<puerto_contenedor> <nombre_imagen> | Mapea un puerto del contenedor al host. |
| Listar Contenedores (Corriendo) | docker ps | Muestra los contenedores actualmente en ejecución. |
| Listar Todos (Corriendo y Detenidos) | docker ps --all | Muestra todos los contenedores, independientemente de su estado. |
| Iniciar/Detener/Reiniciar | docker start|stop|restart <nombre_contenedor> | Inicia o detiene un contenedor existente. docker stop envía una señal SIGTERM para un apagado ordenado. |
| Eliminar un Contenedor | docker rm <nombre_contenedor> | Elimina un contenedor detenido. |
| Entrar al Contenedor | docker exec -it <nombre_contenedor> sh | Abre un shell interactivo dentro de un contenedor en ejecución. |
| Ver Logs | docker logs -f <nombre_contenedor> | Muestra y sigue los logs del contenedor. |
| Inspeccionar Contenedor | docker inspect <nombre_contenedor> | Muestra detalles del contenedor, típicamente en formato JSON. |
| Monitorizar Recursos | docker stats | Muestra estadísticas de uso de recursos en tiempo de ejecución. |
Docker Avanzado: Buenas Prácticas en Imágenes y Seguridad
Construcciones Multi-Etapa (Multi-stage Builds)
Las construcciones multi-etapa optimizan los Dockerfiles manteniéndolos legibles. Permiten crear una imagen de producción pequeña y segura que solo contiene el binario o los artefactos necesarios, sin incluir las herramientas de desarrollo.
- Uso: Se usan múltiples instrucciones
FROM, cada una iniciando una nueva etapa. - Copia Selectiva: Se utiliza
COPY --from=<etapa>para copiar artefactos de una etapa previa. - Nombramiento de Etapas: Es mejor nombrar las etapas con
FROM <imagen> AS <NOMBRE>para referenciarlas más fácilmente y evitar que se rompa la copia si se reordenan las instrucciones:COPY --from=build /bin/hello /bin/hello. - Depuración: Puedes construir solo hasta una etapa específica usando:
docker build --target <etapa> -t hello .. - BuildKit: Es el builder recomendado, ya que solo procesa las etapas de las que depende el objetivo, a diferencia del legacy builder que procesa todas las etapas hasta el objetivo.
Seguridad en Imágenes y Contenedores
| Práctica | Detalle |
|---|---|
| Imágenes Base | Utiliza imágenes oficiales o verificadas de fuentes fiables. Comienza con una imagen base mínima e incluye solo las dependencias esenciales para minimizar vulnerabilidades. |
| Escaneo | Escanea imágenes y contenedores regularmente en busca de vulnerabilidades conocidas (ej. usando herramientas como Trivy o Docker Scout). |
| Privilegios | Sigue el principio del mínimo privilegio. Ejecuta los contenedores como usuarios no root. |
| Sistema de Archivos | Usa sistemas de archivos de solo lectura siempre que sea posible. |
| Firma de Contenido | Habilita Docker Content Trust (DCT) para asegurar que solo utilizas imágenes firmadas. |
Docker Compose (Gestión de Aplicaciones Multi-Contenedor)
Docker Compose es una herramienta que simplifica la gestión de aplicaciones multi-contenedor. Permite definir y orquestar múltiples contenedores (servicios, redes, volúmenes) en un único archivo YAML, típicamente docker-compose.yml.
- Diferencia clave con Docker: Docker gestiona contenedores individuales, mientras que Docker Compose coordina múltiples contenedores que trabajan juntos.
- Uso Ideal: Es especialmente útil para entornos de desarrollo y pruebas donde se requiere una configuración rápida y fluida de múltiples servicios (ej. aplicación web, base de datos y frontend).
- Versión V2: Se recomienda usar la versión más reciente. La V1 (con guion:
docker-compose) ha dejado de recibir actualizaciones; la V2 usadocker compose(sin guion).
Estructura y Comandos Básicos de Compose
El archivo docker-compose.yml define la estructura:
# Nota: En las versiones más recientes de Docker Compose, la versión ya no es necesaria
# version: '3.8' # Opcional en versiones modernas
services:
service1: # Definición de contenedores/servicios
# Configuración del servicio
networks:
network1: # Configuración de redes personalizadas
# Configuración de red
volumes:
volume1: # Definición de volúmenes nombrados
# Configuración de volumen
| Tarea | Comando CLI (V2) | Descripción |
|---|---|---|
| Construir y Desplegar | docker compose up | Construye y ejecuta los contenedores definidos en el yml. |
| Desplegar en Detached | docker compose up -d | Despliega y deja la aplicación corriendo en segundo plano. |
| Detener Aplicación | docker compose stop | Detiene los contenedores. |
| Detener y Eliminar | docker compose down | Detiene y elimina servicios y redes. No elimina volúmenes nombrados por defecto. |
| Eliminar con Volúmenes | docker compose down --volumes o -v | Fuerza la eliminación de servicios, redes y volúmenes nombrados. |
| Escalar Servicio | docker compose up --scale servicio=n | Aumenta la cantidad de contenedores (n) para un servicio específico. |
| Estado de Servicios | docker compose ps | Muestra el estado actual de los contenedores. |
| Logs | docker compose logs | Muestra los logs de los contenedores definidos. |
Gestión de Datos Persistentes (Volúmenes)
Los volúmenes son esenciales para persistir datos entre contenedores y el host, asegurando que los datos no se pierdan al detener o reiniciar los contenedores.
- Volúmenes Nombrados: Tienen un nombre definido por el usuario, facilitando su identificación y gestión. Se definen en la sección
volumesdelymly luego se montan en el servicio. - Montaje de Host (Bind Mounts): Permite compartir directorios del host con el contenedor para facilitar el acceso y la edición de datos. Se usa la sintaxis:
/ruta/en/el/host:/ruta/en/el/contenedor.
| Tarea | Comando CLI (Docker, aplica a volúmenes de Compose) |
|---|---|
| Listar Volúmenes | docker volume ls |
| Inspeccionar Volumen | docker volume inspect <nombre_volumen> |
| Eliminar Volumen | docker volume rm <nombre_volumen> |
| Limpiar Volúmenes no usados | docker volume prune |
Buenas Prácticas Avanzadas de Producción con Compose
Gestión de Secretos y Variables de Entorno
La separación de las configuraciones clave (como credenciales de base de datos y claves de API) del código de la aplicación permite un despliegue más flexible y seguro.
- Riesgo: Nunca codifiques secretos (contraseñas, tokens) en los
Dockerfileso los expongas accidentalmente en las capas de la imagen. - Archivo de Entorno (
env_file): Se recomienda almacenar las variables de entorno en un fichero.envy referenciarlo en eldocker-compose.ymlusando la directivaenv_file: .env. - Seguridad: Este archivo
.envdebe ser excluido del repositorio de código (ej. usando.gitignore), permitiendo que los secretos se carguen en tiempo de ejecución sin exponerse en el gestor de versiones.
Redes y Seguridad de Acceso
- Conectividad Interna: Por defecto, los contenedores definidos en Compose tienen conectividad entre ellos internamente.
- Protección de Bases de Datos: Es una buena práctica de seguridad quitar la exposición de puertos de la base de datos en el
yml(no hacer port binding al host). Aunque el proceso de la base de datos reclame el puerto, este no estará vinculado al Host, protegiendo así la base de datos de la exposición pública. Para acceder a ella, se puede entubar una conexión por SSH.
Límites de Recursos y Reinicios
Para entornos compartidos, es vital limitar los recursos que puede consumir una aplicación para evitar impactar a otras.
- Limitación de Recursos (
deploy: resources): Permite especificar los límites de uso de memoria, CPU o GPU en el servicio.- Límites (
limits): Uso total que puede tener la aplicación (ej.cpus: 1,memory: 1GB). - Reservas (
reservations): RAM y CPU que el contenedor reserva exclusivamente para su funcionamiento.
- Límites (
- Política de Reinicio (
restart_policy): Es crucial usarrestart: alwayspara asegurar que la aplicación arranque automáticamente si el servidor se reinicia.- Configuraciones más detalladas permiten definir condiciones (ej.
on-failure), retrasos (delay), número máximo de intentos (max_attempts) y una ventana de tiempo (window) para los reinicios.
- Configuraciones más detalladas permiten definir condiciones (ej.
Health Checks (Comprobaciones de Salud)
Permiten definir una prueba continua que se lanza al contenedor para verificar que realmente está funcionando, y reiniciarlo si falla.
- Configuración: Se pueden definir el
interval(cada cuánto se lanza la prueba),retries(número de fallos antes de considerar caída),timeout(tiempo máximo de espera para la petición) ystart_period(margen de tiempo al inicio para que la aplicación arranque).
Seguridad del Host y Buenas Prácticas Generales
Para mejorar la seguridad del servidor Linux donde corre Docker Engine:
- Acceso Root Limitado: Limitar el acceso Root para el login (a menudo desactivado por defecto en Ubuntu Server).
- Claves RSA: Se recomienda usar claves RSA (SSH keys) en lugar de contraseñas para iniciar sesión.
- Puedes crear una clave SSH con
ssh-keygen. - Puedes copiar la clave pública al servidor con
ssh-copy-id <usuario>@<servidor>.
- Puedes crear una clave SSH con
- Prevención de Ataques de Fuerza Bruta: Instala Fail2Ban (
apt install fail2ban). Esta aplicación usa reglas de firewall (como IP Tables) para bloquear IPs que realicen demasiados intentos fallidos contra el puerto SSH. - Mantenimiento: Actualiza Docker Engine y sus dependencias frecuentemente para mitigar vulnerabilidades.
- Monitorización: Implementa un sistema de monitorización para registrar logs de las aplicaciones y detectar automáticamente caídas o falta de recursos en el servidor, además de usar
docker statspara monitorear recursos.
Conclusión
Docker y Docker Compose son herramientas fundamentales en el desarrollo de software moderno. Dominar sus comandos y mejores prácticas no solo mejora la eficiencia del desarrollo, sino que también asegura despliegues más seguros y mantenibles en producción. La implementación correcta de estas prácticas permite crear aplicaciones escalables, portátiles y resilientes.
Para continuar tu aprendizaje en contenerización, te recomiendo explorar las estrategias de orquestación con Kubernetes o profundizar en las técnicas de optimización de imágenes para reducir aún más el tamaño y tiempo de inicio de tus aplicaciones.