Docker para principiantes: Una guía práctica sobre contenedores

Cuando empecé a usar Docker, rápidamente me di cuenta de lo poderoso que era. Imagina configurar tu entorno de desarrollo en minutos en lugar de horas, o ejecutar aplicaciones en diferentes máquinas sin el clásico problema de “funciona en mi máquina”.

Docker simplifica cómo construimos, enviamos y ejecutamos aplicaciones al empaquetarlas en contenedores ligeros y portátiles. Ya seas un desarrollador, científico de datos o administrador de sistemas, dominar Docker puede ahorrarte dolores de cabeza y hacer que tus flujos de trabajo sean más eficientes.

En este tutorial, te guiaré a través de los conceptos básicos: instalación de Docker, comprensión de conceptos clave y ejecución de tu primera aplicación en contenedor. Al final, no solo sabrás cómo funciona Docker, sino que también tendrás experiencia práctica usándolo, sentando una base sólida para temas más avanzados. ¡Empecemos!

¿Qué es Docker?

Docker es una plataforma de contenerización de código abierto que simplifica el despliegue de aplicaciones al empaquetar el software y sus dependencias en una unidad estandarizada llamada contenedor. A diferencia de las máquinas virtuales tradicionales, los contenedores de Docker comparten el kernel del sistema operativo anfitrión, lo que los hace más eficientes y ligeros.

Los contenedores aseguran que una aplicación se ejecute de la misma manera en entornos de desarrollo, prueba y producción. Esto reduce problemas de compatibilidad y mejora la portabilidad en diversas plataformas. Debido a su flexibilidad y escalabilidad, Docker se ha convertido en una herramienta crucial en los flujos de trabajo modernos de DevOps y desarrollo nativo en la nube.

Logotipo oficial de Docker.

Instalación de Docker

Docker se puede instalar en varios sistemas operativos, incluidos Windows, macOS y Linux. Aunque la funcionalidad principal es la misma en todas las plataformas, el proceso de instalación varía ligeramente según el sistema. A continuación, encontrarás instrucciones paso a paso para instalar Docker en tu sistema operativo preferido.

Instalación de Docker en Windows

  1. Descarga Docker Desktop for Windows.

Descarga el instalador de Docker Desktop para Windows

  1. Ejecuta el instalador y sigue las instrucciones de configuración.

Instalando Docker Desktop para Windows

  1. Habilita la integración de WSL 2 si se te solicita.
  2. Verifica la instalación ejecutando docker –version en PowerShell.

Verificando la versión de Docker después de la instalación a través de Powershell

5. Inicia la aplicación Docker Desktop desde tu menú de ejecución.

Iniciando la Aplicación Docker Desktop en Windows

Instalando Docker en macOS

  1. Descarga Docker Desktop para Mac.

Descarga el instalador de Docker Desktop para Mac

  1. Abre el archivo descargado .dmg y arrastra Docker a la carpeta de Aplicaciones.
  2. Abre Docker y completa la configuración.
  3. Verifique la instalación usando docker –version en la terminal.

Instalación de Docker en Linux (Ubuntu)

  1. Actualizar listas de paquetes: sudo apt update 
  2. Instalar dependencias: sudo apt install apt-transport-https ca-certificates curl software-properties-common 
  3. Agregar la clave GPG oficial de Docker: curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 
  4. Agregar el repositorio de Docker: sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" 
  5. Instalar Docker: sudo apt install docker-ce  
  6. Verificar la instalación: docker –version

Conceptos básicos de Docker

Ahora que tienes Docker instalado, es posible que estés ansioso por empezar a ejecutar contenedores. Pero antes de hacerlo, es importante entender algunos conceptos clave que forman la base del funcionamiento de Docker. Estos conceptos te ayudarán a navegar Docker de manera más efectiva y evitar errores comunes de principiante.

En el corazón de Docker están las imágenes, que sirven como planos para los contenedores; los contenedores, que son las instancias en ejecución de estas imágenes; y Docker Hub, un repositorio centralizado para compartir y gestionar imágenes.

Exploraremos cada uno de estos conceptos con más detalle.

Imágenes de Docker

Las imágenes de Docker son los bloques de construcción fundamentales de los contenedores. Son inmutables, plantillas de solo lectura que contienen todo lo necesario para ejecutar una aplicación, incluyendo el sistema operativo, el código de la aplicación, el entorno de ejecución y las dependencias.

Las imágenes se construyen utilizando un Dockerfile, que define las instrucciones para crear una imagen capa por capa.

Las imágenes pueden ser almacenadas y recuperadas de registros de contenedores como Docker Hub.

Aquí hay algunos comandos de ejemplo para trabajar con imágenes:

  • docker pull nginx: Obtener la última imagen de Nginx de Docker Hub.
  • docker images: Listar todas las imágenes disponibles en la máquina local.
  • docker rmi nginx: Eliminar una imagen de la máquina local.

Contenedores de Docker

Un contenedor de Docker es una instancia en ejecución de una imagen de Docker. Los contenedores proporcionan un entorno de ejecución aislado donde las aplicaciones pueden ejecutarse sin interferir entre sí o con el sistema anfitrión. Cada contenedor tiene su propio sistema de archivos, red y espacio de procesos, pero comparte el núcleo del anfitrión.

Los contenedores siguen un ciclo de vida simple que implica creación, inicio, detención y eliminación. Aquí hay un desglose de los comandos comunes de gestión de contenedores:

  1. Crear un contenedor: docker create o docker run
  2. Iniciando un contenedor: docker start
  3. Deteniendo un contenedor: docker stop
  4. Reiniciando un contenedor: docker restart
  5. Eliminando un contenedor: docker rm

Veamos un ejemplo práctico. El siguiente comando ejecuta un contenedor de Nginx en modo desacoplado (ejecutándose en segundo plano), mapeando el puerto 80 dentro del contenedor al puerto 8080 en la máquina host:

docker run -d -p 8080:80 nginx

Después de ejecutar este comando, Docker descargará la imagen de Nginx (si no está disponible), creará un contenedor y lo iniciará.

Para verificar todos los contenedores en ejecución y detenidos:

docker ps -a

Esto mostrará una lista de todos los contenedores y detalles como su estado y puertos asignados.

Hub de Docker

El Hub de Docker es un servicio de registro basado en la nube para encontrar, almacenar y distribuir imágenes de contenedores. Los usuarios pueden subir imágenes personalizadas al Hub de Docker y compartirlas públicamente o de forma privada.

Aquí tienes algunos comandos para interactuar con el Hub de Docker:

  • docker login: Autenticarse en el Hub de Docker.
  • docker push my-image: Subir una imagen personalizada a Docker Hub.
  • docker search ubuntu: Buscar imágenes oficiales y de la comunidad.
  • docker pull ubuntu: Descargar una imagen de Ubuntu desde Docker Hub.

¿Nuevo en la contenerización? Obtén una sólida base con el curso de Conceptos de Contenerización y Virtualización.

Ejecutando tu Primer Contenedor de Docker

Ahora que hemos cubierto los conceptos clave de Docker, ¡es hora de ponerlos en acción! Comencemos ejecutando nuestro primer contenedor para asegurarnos de que Docker esté instalado correctamente y funcione según lo esperado.

Para probar tu instalación de Docker, abre PowerShell (Windows) o Terminal (Mac y Linux) y ejecuta:

docker run hello-world

Esto descarga la imagen hello-world desde DockerHub y la ejecuta en un contenedor.

Ejemplo de la imagen hello-world de Docker

Ahora, vamos un paso más allá y ejecutemos una aplicación del mundo real: un servidor web Nginx. Ejecuta el siguiente comando:

docker run -d -p 8080:80 nginx

El comando anterior realiza lo siguiente:

  • La bandera -d ejecuta el contenedor en modo desvinculado, lo que significa que se ejecuta en segundo plano.
  • La bandera -p 8080:80 mapea el puerto 80 dentro del contenedor al puerto 8080 en tu máquina local, permitiéndote acceder al servidor web.

Una vez que el comando se ejecute con éxito, abre un navegador y visita: http://localhost:8080

Accediendo al servidor web en localhost:8080

Deberías ver la página de bienvenida predeterminada de Nginx, ¡confirmando que tu servidor web está funcionando dentro de un contenedor!

También verás un contenedor ejecutándose en tu Docker Desktop:

Contenedor de Nginx ejecutándose en el puerto 8080

Construyendo Tu Primera Imagen Docker

Hasta ahora, hemos estado utilizando imágenes preconstruidas de Docker Hub. Pero, ¿qué pasa si necesitas un entorno personalizado adaptado a tu aplicación? Ahí es donde entra la construcción de tu propia imagen de Docker..

Crear una imagen de Docker implica escribir un Dockerfile, un script que automatiza la construcción de imágenes. Esto garantiza consistencia y portabilidad en diferentes entornos. Una vez que se construye una imagen, se puede ejecutar como un contenedor para ejecutar aplicaciones en un entorno aislado.

En esta sección, aprenderemos los fundamentos de escribir un Dockerfile, construir una imagen personalizada y ejecutarla como un contenedor.

Conceptos básicos de Dockerfile

Un Dockerfile es un script que contiene una serie de instrucciones que definen cómo se construye una imagen de Docker. Automatiza el proceso de creación de imágenes, asegurando consistencia a través de entornos. Cada instrucción en un Dockerfile crea una nueva capa en la imagen. Aquí hay un desglose de un ejemplo de Dockerfile para una aplicación simple de Python Flask:

# Imagen base que contiene el entorno de ejecución de Python FROM python:3.9 # Establecer el directorio de trabajo dentro del contenedor WORKDIR /app # Copiar los archivos de la aplicación del host al contenedor COPY . /app # Instalar las dependencias listadas en requirements.txt RUN pip install -r requirements.txt # Definir el comando para ejecutar la aplicación Flask cuando el contenedor se inicie CMD ["python", "app.py"]

En el comando anterior:

  • -v my-volume:/app/data monta el almacenamiento my-volume en el directorio /app/data dentro del contenedor.
  • Cualquier dato almacenado en /app/data persistirá incluso si el contenedor se detiene o se elimina.

Desglosando el Dockerfile anterior:

  • FROM python:3.9: Especifica la imagen base con Python 3.9 preinstalado.
  • WORKDIR /app: Establece /app como el directorio de trabajo dentro del contenedor.
  • COPY . /app: Copia todos los archivos desde el directorio actual del host a /app en el contenedor.
  • RUN pip install -r requirements.txt: Instala todas las dependencias requeridas dentro del contenedor.
  • CMD ["python", "app.py"]: Define el comando a ejecutar cuando el contenedor se inicia.

Construyendo y ejecutando la imagen

Una vez que se define el Dockerfile, puedes construir y ejecutar la imagen usando los siguientes comandos:

Paso 1: Construir la imagen

docker build -t my-flask-app .

El comando anterior:

  • Utiliza el directorio actual (.) como contexto de construcción.
  • Lee el archivo Dockerfile y ejecuta sus instrucciones.
  • Etiqueta (-t) la imagen resultante como my-flask-app.

Paso 2: Ejecutar la imagen como contenedor

docker run -d -p 5000:5000 my-flask-app

El comando anterior:

  • Ejecuta el contenedor en modo desprendido (-d).
  • Mapea el puerto 5000 dentro del contenedor al puerto 5000 en el host (-p 5000:5000).

Una vez en funcionamiento, puedes acceder a la aplicación Flask navegando a http://localhost:5000 en un navegador.

Volúmenes y Persistencia en Docker

Por defecto, los datos dentro de un contenedor de Docker son temporales—una vez que el contenedor se detiene o se elimina, los datos desaparecen. Para persistir datos a través de reinicios del contenedor y compartirlos entre múltiples contenedores, Docker proporciona volúmenes, un mecanismo integrado para gestionar el almacenamiento persistente de manera eficiente.

A diferencia de almacenar datos dentro del sistema de archivos del contenedor, los volúmenes son gestionados por separado por Docker, lo que los hace más eficientes, flexibles y fáciles de respaldar.

En la siguiente sección, exploraremos cómo crear y usar volúmenes de Docker para garantizar la persistencia de datos en tus contenedores.

Creación y uso de volúmenes de Docker

Paso 1: Crear un volumen

Antes de usar un volumen, necesitamos crear uno. Ejecuta el siguiente comando:

docker volume create my-volume

Esto crea un volumen con nombre llamado my-volume, que Docker gestionará por separado de cualquier contenedor específico.Paso 2: Usa el volumen en un contenedor

Ahora, comencemos creando un contenedor y montando el volumen dentro de él:

docker run -d -v my-volume:/app/data my-app

En el comando anterior:

  • -v my-volume:/app/data monta el almacenamiento my-volume en el directorio /app/data dentro del contenedor.
  • Cualquier dato almacenado en /app/data persistirá incluso si el contenedor se detiene o se elimina.

Docker Compose para Aplicaciones Multi-Contenedor

Hasta ahora, hemos estado trabajando con aplicaciones de un solo contenedor, pero muchas aplicaciones del mundo real requieren múltiples contenedores para funcionar juntos. Por ejemplo, una aplicación web podría necesitar un servidor backend, una base de datos y una capa de almacenamiento en caché, cada uno ejecutándose en su propio contenedor. Gestionar estos contenedores manualmente con comandos docker run separados puede volverse tedioso rápidamente.

Es aquí donde entra en juego Docker Compose.

¿Qué es Docker Compose?

Docker Compose es una herramienta que simplifica la gestión de aplicaciones multi-contenedor. En lugar de ejecutar múltiples comandos docker run, puedes definir toda una pila de aplicación utilizando un archivo docker-compose.yml y desplegarlo con un solo comando.

Creación de un archivo Docker Compose

Ahora, creemos un ejemplo del mundo real: una aplicación Node.js simple que se conecta a una base de datos MongoDB. En lugar de gestionar los dos contenedores por separado, los definiremos en un archivo docker-compose.yml.

Así es como definimos nuestra configuración multi-contenedor en Docker Compose:

version: '3' services: web: build: . ports: - "3000:3000" depends_on: - database database: image: mongo volumes: - db-data:/data/db volumes: db-data:

Desglosando el archivo anterior:

  • version: '3': Especifica la versión de Docker Compose.
  • services:: Define servicios individuales (contenedores).
  • web:: Define la aplicación web Node.js.
  • database:: Define el contenedor de la base de datos MongoDB.
  • volumes:: Crea un volumen con nombre (db-data) para la persistencia de datos de MongoDB.

Ejecución de aplicaciones multi-contenedor

Una vez que el archivo docker-compose.yml esté listo, podemos lanzar toda la pila de aplicaciones con un solo comando:

docker-compose up -d

El comando anterior inicia tanto los contenedores web como de base de datos en modo desatacado (-d).

Para detener todos los servicios, utiliza:

docker-compose down

Esto detiene y elimina todos los contenedores mientras se preservan los volúmenes y la configuración de red.

Conceptos básicos de la red de Docker

Hasta ahora, nos hemos centrado en ejecutar contenedores y administrar el almacenamiento, pero ¿qué sucede cuando los contenedores necesitan comunicarse entre sí? En la mayoría de las aplicaciones del mundo real, los contenedores no operan de forma aislada, necesitan intercambiar datos, ya sea que un servidor web hable con una base de datos o que los microservicios interactúen entre sí.

Docker proporciona una variedad de opciones de redes para dar cabida a diferentes casos de uso, desde redes internas aisladas hasta configuraciones accesibles externamente.

¿Listo para mejorar tus habilidades con Docker? ¡Inscríbete en Docker Intermedio para explorar construcciones en múltiples etapas, redes avanzadas y más!

¿Qué es la red de Docker?

La red de Docker es una característica incorporada que permite que los contenedores se comuniquen entre sí, ya sea en el mismo host o a través de múltiples hosts en un entorno distribuido. Proporciona aislamiento de red, segmentación y opciones de conectividad adecuadas para diferentes escenarios de implementación.

Docker admite varios tipos de redes, cada uno sirviendo diferentes casos de uso:

  • Bridge (predeterminado): Los contenedores en el mismo host se comunican a través de una red virtual interna. Cada contenedor recibe su dirección IP privada dentro de la red de puente y pueden alcanzarse entre sí a través de los nombres de los contenedores.
    • Ejemplo: docker network create my-bridge-network
    • Ideal para ejecutar varios contenedores en un único host que necesitan comunicarse de forma segura sin exponer servicios externamente.
  • Host: Los contenedores comparten la pila de red del host y utilizan directamente la dirección IP y los puertos del host.
    • Ejemplo: docker run --network host nginx
    • Útil cuando se necesita alto rendimiento y no se requiere aislamiento de red, como al ejecutar agentes de monitoreo o aplicaciones de baja latencia.
  • Superposición: Permite la comunicación de contenedores en diferentes hosts creando una red distribuida.
    • Ejemplo: docker network create --driver overlay my-overlay-network
    • Diseñado para implementaciones orquestadas como Docker Swarm, donde los servicios abarcan múltiples nodos.
  • Macvlan: Asigna una dirección MAC única a cada contenedor, haciendo que aparezca como un dispositivo físico en la red.
    • Ejemplo: docker network create -d macvlan --subnet=192.168.1.0/24 my-macvlan
    • Se utiliza cuando los contenedores necesitan acceso directo a la red, como al integrar sistemas heredados o interactuar con redes físicas.

Ejecutando contenedores en redes personalizadas

Vamos a repasar cómo configurar y usar una red de puente personalizada para la comunicación entre contenedores.

Paso 1: Crear una red personalizada

Antes de ejecutar contenedores, primero necesitamos crear una red dedicada:

docker network create my-custom-network

Este comando crea una red aislada a la que los contenedores pueden unirse para la comunicación entre contenedores.

Paso 2: Ejecutar contenedores en la red

Ahora, vamos a iniciar dos contenedores y conectarlos a nuestra red recién creada:

docker run -d --network my-custom-network --name app1 my-app docker run -d --network my-custom-network --name app2 my-app
  • La bandera --network my-custom-network adjunta el contenedor a la red especificada.
  • La bandera --name asigna un nombre único al contenedor, facilitando su referencia.

Ahora tanto app11 como app2 pueden comunicarse usando sus nombres de contenedor. Puedes probar la conectividad usando el comando ping dentro de uno de los contenedores:

docker exec -it app1 ping app2

Si todo está configurado correctamente, verás una respuesta confirmando que los contenedores pueden comunicarse.

Inspección de redes de Docker

Para verificar las configuraciones de red y los contenedores conectados, usa:

docker network inspect my-custom-network

Este comando proporciona detalles sobre la red, incluyendo rangos de IP, contenedores conectados y configuraciones.

Exponer y publicar puertos

Cuando se ejecutan contenedores que necesitan ser accesibles externamente, puedes exponer puertos específicos.

Por ejemplo, para ejecutar un servidor web Nginx y exponerlo en el puerto 8080 de tu máquina local, usa:

docker run -d -p 8080:80 nginx

Esto mapea el puerto 80 dentro del contenedor al puerto 8080 en el host, haciendo que el servicio sea accesible a través de http://localhost:8080.

Mejores prácticas para la red de Docker

  • Usa redes personalizadas: Evita usar la red por defecto de bridge para implementaciones en producción para reducir el acceso no intencionado entre contenedores.
  • Aprovechar el descubrimiento basado en DNS: En lugar de codificar direcciones IP, utiliza nombres de contenedores para habilitar el descubrimiento dinámico de servicios.
  • Restringir la exposición externa: Utiliza cortafuegos o políticas de red para controlar el acceso a los servicios.
  • Monitorear el tráfico: Utiliza herramientas como docker network inspect, Wireshark o Prometheus para analizar el tráfico de red y detectar anomalías.
  • Optimizar redes superpuestas: Si implementas en una configuración distribuida, ajusta las redes superpuestas para reducir la latencia aprovechando las opciones de enrutamiento local del host.

Docker Mejores Prácticas y Próximos Pasos

Ahora que has aprendido los fundamentos de Docker, es hora de mejorar tus habilidades y adoptar las mejores prácticas que te ayudarán a construir aplicaciones contenerizadas seguras, eficientes y mantenibles.

Las siguientes mejores prácticas te ayudarán a optimizar tus flujos de trabajo de Docker y evitar errores comunes.

  • Utiliza imágenes base oficiales: Siempre prefiere imágenes base oficiales y bien mantenidas para garantizar seguridad y estabilidad. Las imágenes oficiales están optimizadas, se actualizan regularmente y tienen menos probabilidades de contener vulnerabilidades.
  • Mantén las imágenes pequeñas: Reduce el tamaño de la imagen eligiendo imágenes base mínimas (por ejemplo, python:3.9-slim en lugar de python:3.9). Elimina dependencias y archivos innecesarios para optimizar el almacenamiento y los tiempos de descarga.
  • Utiliza construcciones de múltiples etapas: Optimiza los Dockerfiles separando las dependencias de construcción y de ejecución. Las construcciones de múltiples etapas aseguran que solo se incluyan los artefactos necesarios en la imagen final, reduciendo el tamaño y la superficie de ataque.
  • Etiqueta las imágenes correctamente: Siempre utiliza etiquetas versionadas (por ejemplo, mi-app:v1.0.0) en lugar de latest para evitar actualizaciones inesperadas al descargar imágenes.
  • Escanea imágenes en busca de vulnerabilidades: Utiliza herramientas de escaneo de seguridad como docker scan, Trivy o Clair para identificar y remediar vulnerabilidades de seguridad en tus imágenes antes de implementarlas.
  • Administra variables de entorno de forma segura: Evita almacenar credenciales sensibles dentro de las imágenes. Utiliza secretos de Docker, variables de entorno o herramientas externas de gestión de secretos como AWS Secrets Manager o HashiCorp Vault.
  • Usa archivos .dockerignore: Excluye archivos innecesarios (por ejemplo, .git, node_modules, venv) para reducir el tamaño del contexto de construcción y evitar la inclusión accidental de archivos sensibles en las imágenes.
  • Habilita el registro y monitoreo: Utiliza herramientas como Prometheus, Grafana y Fluentd para registros de contenedores y monitoreo. Inspecciona los registros usando docker logs y habilita el registro estructurado para una mejor observabilidad.

Una vez que hayas dominado lo básico de Docker, hay muchos temas avanzados por explorar. Aquí hay algunas áreas que vale la pena explorar a continuación:

  • Docker Swarm & Kubernetes: Explora Docker Swarm (clúster incorporado) y Kubernetes (orquestación de grado empresarial con escalado automático y descubrimiento de servicios) para orquestación de nivel de producción.
  • Mejores prácticas de seguridad de contenedores: Para asegurar aplicaciones contenerizadas, sigue las directrices del CIS Docker Benchmark e implementa Control de Acceso Basado en Roles (RBAC).
  • Pipelines CI/CD con Docker: Automatiza la construcción de imágenes, escaneos de seguridad y despliegues utilizando GitHub Actions, GitLab CI o Jenkins.
  • Desarrollo nativo en la nube: Aprovecha Docker con plataformas en la nube como AWS ECS, Azure Container Instances y Google Cloud Run para despliegues escalables y gestionados.
  • Estrategias de persistencia de datos: Para una gestión óptima del almacenamiento, entiende las diferencias entre volúmenes de Docker, enlaces de montaje y tmpfs.

Conclusión

Docker ha revolucionado la forma en que los desarrolladores crean, envían y ejecutan aplicaciones, convirtiéndose en una herramienta esencial para el desarrollo de software moderno.

En este tutorial, cubrimos:

  • Qué es Docker y por qué es importante
  • Cómo instalar y ejecutar tu primer contenedor
  • Conceptos clave como imágenes, contenedores y redes
  • Almacenamiento persistente con volúmenes de Docker
  • Aplicaciones de varios contenedores con Docker Compose
  • Mejores prácticas para seguridad, rendimiento y escalabilidad

¡Pero esto es solo el principio! Si deseas profundizar en tu experiencia con Docker, puedes realizar un curso de nivel principiante Introducción a Docker. Para un conocimiento más avanzado, puedes realizar un curso Docker Intermedio que cubre compilaciones de múltiples etapas, herramientas de redes de Docker y Docker Compose. Finalmente, también puedes optar por la certificación de Docker, ¡consulta La Guía Completa de Certificación de Docker (DCA) para 2025 si estás interesado!

Source:
https://www.datacamp.com/tutorial/docker-tutorial