Horario Laboral: De lunes a viernes, de 10AM a 10PM

imagen destacada del post con un texto en el centro que dice Aprende a crear contenedores con Dockerfile paso a paso y abajo del texto aparece la categoria del post

Introducción a la creación de imágenes de contenedor con Dockerfile

En la era actual del desarrollo de software y la administración de sistemas, la contenerización se ha convertido en una práctica esencial para garantizar entornos consistentes y desplegables rápidamente. Docker lidera esta revolución con su capacidad para empaquetar aplicaciones y sus dependencias en contenedores portables y eficientes. Sin embargo, para sacar el máximo provecho a Docker, es indispensable aprender a crear imágenes propias que reflejen las necesidades específicas de tu proyecto. Aquí es donde entra en juego el Dockerfile, un archivo que define, paso a paso, cómo construir una imagen personalizada.

Este artículo técnico y exhaustivo ofrece una guía completa para entender, diseñar y optimizar Dockerfiles, abarcando desde sus conceptos básicos hasta las mejores prácticas para maximizar el rendimiento y la reutilización mediante la caché de capas.

¿Qué es un Dockerfile y por qué es fundamental?

Un Dockerfile es un archivo de texto que contiene una serie de instrucciones secuenciales que Docker interpreta para construir una imagen. Cada línea representa un comando o configuración que modifica o añade contenido a la imagen base.

Estas son algunas de las funcionalidades que permiten las instrucciones dentro de un Dockerfile:

  • Seleccionar la imagen base, típicamente un sistema operativo o entorno preconfigurado.
  • Copiar archivos y carpetas del sistema host hacia la imagen que se está creando.
  • Ejecutar comandos como instalaciones o configuraciones internas.
  • Establecer el comando o punto de entrada con el cual iniciará el contenedor.

Por ejemplo, en un proyecto basado en Node.js, puedes definir un Dockerfile que parta de una imagen oficial de Node, copie el código fuente, instale las dependencias y defina el servidor que deseas ejecutar, todo automatizado y reproducible.

Estructura básica de un Dockerfile

La creación de un Dockerfile sigue un patrón lógico y secuencial. Vamos a detallar las principales instrucciones que componen un Dockerfile típico:

FROM: Definir la imagen base

La instrucción FROM especifica la imagen a partir de la cual empezarás a construir la tuya propia. Es el primer paso esencial, porque establece el entorno base.

Ejemplo:

FROM node:18

WORKDIR: Establecer el directorio de trabajo

El comando WORKDIR crea y establece el directorio en el que se ejecutarán las instrucciones posteriores. Si el directorio no existe, se crea automáticamente.

Ejemplo:

WORKDIR /app

COPY: Copiar archivos del host a la imagen

La instrucción COPY copia archivos o carpetas desde tu máquina local (host) hacia un directorio dentro de la imagen en construcción.

Ejemplo, copiar el archivo package.json al directorio actual dentro de la imagen:

COPY package.json .

RUN: Ejecutar comandos durante la construcción

Con RUN ejecutamos comandos dentro del contenedor temporal que se genera mientras se construye la imagen, como instalar dependencias o preparar el entorno.

Ejemplo de instalación con npm:

Guía completa sobre Cloud Native y el ecosistema CNCFGuía completa sobre Cloud Native y el ecosistema CNCF
RUN npm install

CMD: Definir el comando por defecto al iniciar el contenedor

El comando CMD indica qué proceso se ejecutará cuando el contenedor se inicie a partir de esta imagen. Es el punto de entrada principal.

Ejemplo de ejecución de un servidor Node.js:

CMD ["node", "server.js"]

Archivo .dockerignore: optimizando el contexto de build

Para mejorar el rendimiento durante la creación de imágenes, es vital controlar qué archivos y carpetas se incluyen en el contexto de build, es decir, el conjunto de ficheros que Docker puede acceder para copiar o usar.

El archivo .dockerignore funciona similar a un .gitignore y permite excluir archivos o directorios que no serán necesarios en la imagen, como node_modules o archivos temporales.

  • Evita enviar al servidor Docker archivos innecesarios, acelerando la construcción.
  • Reduce el tamaño del contexto de build.
  • Minimiza la posibilidad de copiar información sensible o irrelevante.

Construcción de la imagen: docker build y el contexto de build

Para generar una imagen a partir de un Dockerfile se utiliza el comando docker build.

Ejemplo de uso:

docker build -t demo-node .

Donde:

  • -t demo-node etiqueta la imagen con el nombre demo-node.
  • . indica que el contexto de build es el directorio actual y también donde está el Dockerfile.

Contexto de build: Docker envía el contenido del directorio especificado al servidor Docker, que puede estar local o remoto, comprimido para su transferencia. Esto significa que solo pueden copiarse archivos dentro de este contexto.

Buenas prácticas para el contexto

  • Mantener el contexto pequeño para acelerar el envío y procesamiento.
  • Utilizar un archivo .dockerignore eficiente para descartar archivos innecesarios.
  • Organizar los archivos y la estructura del proyecto pensando en la contenerización.

Ejemplo completo y explicación detallada de un Dockerfile para una app Node.js

 FROM node:18 WORKDIR /app COPY package.json . RUN npm install COPY . . CMD ["node", "server.js"] 

Desglose paso a paso:

  1. Se toma como base la imagen oficial de Node.js versión 18.
  2. Se crea y establece el directorio /app donde se ubicará la aplicación.
  3. Se copia únicamente package.json, que contiene las dependencias del proyecto.
  4. Se ejecuta npm install para instalar las dependencias dentro de la capa.
  5. Se copia el resto del código fuente de la aplicación al directorio /app dentro de la imagen.
  6. Se define que al iniciar el contenedor, se ejecutará el comando node server.js.

Esta estructura facilita la reutilización de capas y aprovecha la caché, algo que explicaremos a continuación.

Caché de capas: acelerando la construcción y facilitando la gestión

Docker construye cada instrucción de un Dockerfile como una capa independiente que es inmutable y se identifica por un hash único basado en su contenido.

Esto significa que si una capa no cambia entre construcciones, Docker puede reutilizarla directamente, evitando ejecutar comandos pesados innecesariamente.

Importancia en la secuencia COPY y RUN

Si copiamos todos los archivos y luego ejecutamos npm install, una modificación en cualquier archivo invalida toda la caché posterior, incluyendo la instalación de dependencias.

Por eso, se recomienda copiar primero el archivo package.json, ejecutar npm install y luego copiar el resto del código:

Tipos de bases de datos esenciales para entender su funcionamientoTipos de bases de datos esenciales para entender su funcionamiento
  • Si solo modifico código que no afecta a las dependencias, npm install se reutiliza de la caché.
  • Reduce sensiblemente el tiempo de build después de cambios menores.

Comparativa: Dockerfile optimizado vs Dockerfile básico

Aspecto Dockerfile básico (COPY todo primero) Dockerfile optimizado (COPY package.json)
Reutilización de caché Baja, se invalida fácilmente Alta, evita reinstalar dependencias innecesariamente
Tiempo de construcción tras cambios menores Alto, se repite npm install Bajo, solo recompila capas después del código
Complejidad Muy simple Moderada, requiere orden específico
Buenas prácticas recomendadas No

Profundizando en conceptos fundamentales para un Dockerfile eficiente

Contexto de build: qué es y por qué afecta la performance

El contexto es el conjunto de archivos que Docker interpreta y envía al servidor que construye la imagen. Si el contexto es muy grande, la transferencia tomará más tiempo, incluso si la imagen resultante es pequeña.

Para evitar cargas innecesarias:

  • Ordena y limpia tu proyecto para incluir solo lo necesario.
  • Implementa correctamente el archivo .dockerignore.

Caché de build: cómo aprovecharla para acelerar iteraciones

Docker compara el hash de cada capa generada con las existentes. Si no ha cambiado, reutiliza la capa guardada, ahorrando tiempo.

Recomendaciones:

  • Organiza las instrucciones para que las que cambian con menos frecuencia estén antes.
  • Evita incluir en capas tempranas archivos que cambian constantemente.

Ejemplo práctico: construyendo y ejecutando la imagen de Node.js

Una vez definido el Dockerfile, el proceso típico es:

  1. Ejecutar el comando docker build -t demo-node ..
  2. Verificar que la imagen fue creada con docker images.
  3. Crear y ejecutar un contenedor con docker run -d -p 8000:8000 demo-node.
  4. Interaccionar con el servidor Node.js dentro del contenedor mediante HTTP, por ejemplo con curl.

Este flujo automatiza y encapsula el despliegue, facilitando la portabilidad.

Avanzando: otras instrucciones y detalles útiles del Dockerfile

EXPOSE

Permite documentar el puerto en el que la aplicación escuchará dentro del contenedor. Aunque no mapea puertos por sí mismo, es una referencia.

ENV

Define variables de entorno para configurar el comportamiento del contenedor.

ENTRYPOINT

Utilizado para configurar el comando principal que no puede ser sobrescrito fácilmente, útil para asegurar que el contenedor funcione siempre de una manera determinada.

LABEL

Para añadir metadatos como autor, versión y mantenimiento, facilitando el manejo y documentación.

Errores comunes y recomendaciones para evitarlos

  • No ignorar carpeta node_modules en Dockerfile, lo cual incrementa el tamaño de la imagen.
  • Modificar archivos fuera del contexto de build, causando errores en COPY.
  • Ignorar la caché puede producir builds lentas e ineficientes.
  • Olvidar establecer correctamente el comando CMD o ENTRYPOINT, impidiendo que el contenedor arranque correctamente.

Palabras clave relacionadas y su importancia en Dockerfile

Dockerfile

Es el archivo maestro que define la imagen. Entenderlo es fundamental para cualquier profesional que trabaje con contenedores. Facilita la automatización del entorno.

Contenedor

Instancia en ejecución de una imagen. Los Dockerfiles permiten crear imágenes optimizadas que definirán el comportamiento de los contenedores.

Imagen

Paquete virtualizado que contiene el sistema operativo base, el software y la configuración. Crearla correctamente implica optimizar la construcción y el tamaño.

Caché de build

Permitió acelerar las construcciones posteriores reutilizando capas que no cambiaron. Es crucial diseñar Dockerfiles eficientes para maximizar este beneficio.

Guía práctica para usar Multi-Stage-Build y trabajar con contenedoresGuía práctica para usar Multi-Stage-Build y trabajar con contenedores

Contexto de build

Conjunto de archivos enviados para construir la imagen. Mantenerlo pequeño optimiza los tiempos de build y reduce la transferencia innecesaria.

.dockerignore

Archivo para excluir archivos y carpetas del contexto de build. Mantenerlo actualizado es clave para una construcción rápida y segura.

Docker Run

Comando para crear y ejecutar contenedores basados en imágenes. La configuración previa en el Dockerfile facilita la parametrización de esta ejecución.

Node.js

Ejemplo de entorno de ejecución para aplicaciones JavaScript utilizado como caso práctico para explicar el Dockerfile y la instalación de dependencias.

Si quieres complementar esta guía con una explicación práctica en video, te invitamos a ver este recurso visual que te ayudará a consolidar lo aprendido.

Preguntas frecuentes sobre Dockerfile y creación de imágenes

¿Cuánto se tarda en aprender Docker?

El tiempo para aprender Docker varía según la experiencia previa y la dedicación del usuario. Generalmente, un principiante puede comprender los conceptos esenciales en unos pocos días, abarcando contenedores, imágenes y Dockerfiles. Sin embargo, alcanzar un nivel avanzado, optimizando imágenes y flujos de trabajo, puede requerir semanas o meses con práctica continua.

¿Cuál es la herramienta para crear imágenes de contenedores a partir de un Dockerfile?

La herramienta estándar es el propio Docker Build. No obstante, existe Kaniko, diseñada para construir imágenes utilizando un Dockerfile dentro de un contenedor o en entornos de Kubernetes, sin necesidad del demonio de Docker. Esto aumenta la seguridad en entornos donde el acceso al demonio implica riesgos, especialmente en infraestructuras compartidas.

¿Es difícil aprender Docker?

Aprender Docker es accesible para personas con conocimientos básicos de administración de sistemas y programación. La dificultad aumenta en función de la profundidad y el escenario de uso, como orquestación con Kubernetes. La dedicación y el uso práctico facilitan la curva de aprendizaje. Además, la comunidad y la documentación oficial son recursos valiosos.

¿Por qué utilizar dos instrucciones COPY en lugar de una sola?

Dividir la copia en dos pasos («package.json» primero y el resto después) permite aprovechar la caché de build, evitando reinstalar dependencias si solo se modifica código fuente posterior. Esto reduce considerablemente el tiempo de construcción en iteraciones de desarrollo.

¿Qué pasa si no uso un archivo .dockerignore?

Sin un .dockerignore, Docker incluirá todo el contenido del directorio en el contexto de build, lo que puede hacer la transferencia y construcción más lentas y, en ocasiones, incluir archivos innecesarios o sensibles en la imagen.

¿Cómo puedo asegurar que el contenedor escuche en el puerto correcto?

Además de exponer el puerto con la instrucción EXPOSE en el Dockerfile (que es informativa), debes mapearlo correctamente en el comando docker run utilizando la opción -p, por ejemplo -p 8000:8000.

¿Qué diferencias hay entre CMD y ENTRYPOINT?

CMD define el comando por defecto que puede ser sobrescrito al correr el contenedor, mientras que ENTRYPOINT establece un comando inalterable que se ejecuta siempre, pero puede aceptar parámetros adicionales.

¿Puedo crear imágenes Docker sin acceso al demonio Docker?

Sí, herramientas como Kaniko permiten construir imágenes sin acceso al demonio Docker, ideal para entornos con restricciones de seguridad o en entornos de CI/CD integrados en Kubernetes.

Conclusión y próximos pasos

La creación de imágenes de contenedor a través de Dockerfiles es una habilidad clave en el ecosistema DevOps y desarrollo moderno. Dominar este proceso no solo mejora la consistencia y portabilidad de tus aplicaciones, sino que también optimiza la eficiencia y la velocidad del despliegue. Recuerda siempre tener presente el contexto de build y la gestión inteligente de la caché para agilizar tu flujo de trabajo.

Cómo ejecutar tests unitarios y trabajar con contenedores eficientementeCómo ejecutar tests unitarios y trabajar con contenedores eficientemente

¿Querés mantenerte actualizado con las últimas tendencias en automatización, inteligencia artificial y transformación digital? Visitá nuestro blog de Código6 y descubrí guías, casos de éxito y noticias relevantes para potenciar tu empresa. Ingresá al blog y explorá los recursos más recientes.

Share

Leave A Comment

Descubre el poder de la IA

Sumérgete en una experiencia transformadora hacia el futuro de la innovación, explorando el potencial ilimitado de la inteligencia artificial en cada interacción.

Impulsa tu empresa con automatización, inteligencia artificial, desarrollo web y SEO técnico. Descubre la transformación digital con Código6.

© 2025 Codigo6 Todos los derechos reservados.