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:

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:
- Se toma como base la imagen oficial de Node.js versión 18.
- Se crea y establece el directorio
/app
donde se ubicará la aplicación. - Se copia únicamente
package.json
, que contiene las dependencias del proyecto. - Se ejecuta
npm install
para instalar las dependencias dentro de la capa. - Se copia el resto del código fuente de la aplicación al directorio
/app
dentro de la imagen. - 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:

- 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 | Sí |
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:
- Ejecutar el comando
docker build -t demo-node .
. - Verificar que la imagen fue creada con
docker images
. - Crear y ejecutar un contenedor con
docker run -d -p 8000:8000 demo-node
. - 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
oENTRYPOINT
, 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.

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.

¿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.
Leave A Comment