Un Dockerfile es un archivo de texto con instrucciones paso a paso que le dicen a Docker cómo construir tu imagen personalizada.
Imagina que trabajas en el equipo de tecnología de Liverpool. Tienes una aplicación Python que calcula descuentos para el programa de lealtad. Funciona perfecto en tu laptop, pero cuando la subes al servidor de producción, todo falla. Las versiones de librerías no coinciden, falta una dependencia, y el equipo de operaciones no sabe qué instalar. Ese problema clásico —"en mi máquina sí funciona"— es exactamente lo que un Dockerfile resuelve.
El sistema RECETA-IMAGEN
Piensa en el Dockerfile como una receta de cocina. La receta (Dockerfile) siempre produce el mismo platillo (imagen), sin importar en qué cocina (servidor) la prepares. Este sistema se llama RECETA-IMAGEN y tiene tres momentos:
- Escribes el Dockerfile con las instrucciones.
- Construyes la imagen con
docker build. - Ejecutas contenedores desde esa imagen en cualquier servidor.
Cada instrucción en el Dockerfile agrega una capa a la imagen. Docker apila esas capas como transparencias sobre un proyector: cada una agrega algo nuevo sobre lo anterior.
Las cinco instrucciones esenciales
No necesitas memorizar decenas de comandos. Con estas cinco instrucciones puedes empaquetar el 90% de las aplicaciones reales:
FROM — El punto de partida
FROM le dice a Docker sobre qué base construirás tu imagen. Siempre es la primera instrucción.
FROM python:3.11-slim
Esta línea descarga la imagen oficial de Python 3.11 en su versión ligera (slim). Nunca uses FROM python:latest en producción. La versión exacta garantiza que tu imagen funcione igual hoy y dentro de seis meses.
WORKDIR — Tu carpeta de trabajo
WORKDIR define el directorio donde Docker ejecutará los comandos siguientes. Es como hacer cd antes de trabajar.
WORKDIR /app
A partir de aquí, todo sucede dentro de /app. Si la carpeta no existe, Docker la crea automáticamente.
COPY — Llevar tus archivos al contenedor
COPY copia archivos desde tu máquina hacia la imagen.
COPY requirements.txt .
COPY app.py .
El punto (.) significa "copia aquí", es decir, dentro del WORKDIR que definiste. Primero copia requirements.txt antes que el código porque Docker reutiliza capas anteriores si no cambiaron. Así, si solo editas app.py, Docker no reinstala las dependencias desde cero.
RUN — Ejecutar comandos durante la construcción
RUN ejecuta comandos mientras Docker construye la imagen. Úsalo para instalar dependencias.
RUN pip install --no-cache-dir -r requirements.txt
El flag --no-cache-dir evita que pip guarde archivos temporales dentro de la imagen. Tu imagen queda más ligera.
CMD — El comando al arrancar el contenedor
CMD define qué se ejecuta cuando alguien corre un contenedor basado en tu imagen.
CMD ["python", "app.py"]
Usa siempre el formato de lista (con corchetes). Ese formato se llama "exec form" y es más confiable que escribirlo como texto plano.
Ejemplo completo: aplicación de descuentos de Liverpool
Supon que tienes estos dos archivos en tu carpeta de proyecto:
requirements.txt
flask==3.0.0
app.py
from flask import Flask, jsonify
app = Flask(__name__)
@app.route("/descuento/<int:precio>")
def calcular_descuento(precio):
descuento = precio * 0.15
precio_final = precio - descuento
return jsonify({
"precio_original": f"${precio:,.0f}",
"descuento_15": f"${descuento:,.0f}",
"precio_final": f"${precio_final:,.0f}"
})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
Ahora crea un archivo llamado exactamente Dockerfile (sin extensión) en esa misma carpeta:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
CMD ["python", "app.py"]
Este Dockerfile le dice a Docker:
- Parte de Python 3.11 slim.
- Trabaja en la carpeta
/app. - Copia e instala las dependencias.
- Copia el código.
- Al arrancar, ejecuta
python app.py.
Cómo construir y ejecutar tu imagen
Abre tu terminal en la carpeta del proyecto y ejecuta:
docker build -t liverpool-descuentos:1.0 .
-t liverpool-descuentos:1.0le pone nombre y versión a tu imagen.- El punto final (
.) le dice a Docker dónde está el Dockerfile (en la carpeta actual).
Verás cómo Docker ejecuta cada instrucción y muestra el progreso capa por capa. Al terminar, prueba con:
docker run -d -p 5000:5000 liverpool-descuentos:1.0
Abre tu navegador en http://localhost:5000/descuento/1200 y verás algo así:
{
"precio_original": "$1,200",
"descuento_15": "$180",
"precio_final": "$1,020"
}
Tu aplicación corre dentro de un contenedor. Cualquier servidor con Docker puede ejecutar exactamente esto, sin instalar Python ni Flask manualmente.
Errores comunes al escribir un Dockerfile
Error 1: Copiar todo antes de instalar dependencias
Muchos principiantes escriben esto:
COPY . .
RUN pip install -r requirements.txt
El problema: cada vez que cambias cualquier archivo, Docker reinstala todas las dependencias desde cero. Eso puede costar varios minutos extra en cada build. La solución es copiar primero requirements.txt, instalar, y luego copiar el resto del código.
Error 2: Usar latest como versión base
FROM python:latest # ❌ Peligroso
FROM python:3.11-slim # ✅ Correcto
latest cambia con el tiempo. Una imagen que funcionaba hoy puede romperse mañana cuando Python libere la versión 3.13. En un equipo como el de FEMSA, donde decenas de servicios dependen entre sí, eso puede causar un apagón de producción.
Error 3: Olvidar el .dockerignore
Cuando usas COPY . ., Docker copia absolutamente todo, incluyendo tu carpeta .git, archivos de configuración local, contraseñas en .env, y carpetas node_modules o __pycache__ que pesan cientos de megabytes.
Crea un archivo .dockerignore junto a tu Dockerfile:
.git
__pycache__
*.pyc
.env
venv/
Así Docker ignora esos archivos al construir la imagen. Tu imagen queda más pequeña y más segura.
Error 4: Ejecutar la app como root
Por defecto, los procesos dentro del contenedor corren como usuario root. Eso es un riesgo de seguridad. En entornos de producción, como los que usa Mercado Libre para sus microservicios, siempre se crea un usuario sin privilegios:
RUN adduser --disabled-password --gecos "" appuser
USER appuser
CMD ["python", "app.py"]
Con USER appuser, el proceso ya no tiene permisos de root dentro del contenedor.
Comparación: con Dockerfile vs. sin Dockerfile
| Situación | Sin Docker | Con Dockerfile |
|---|---|---|
| Nuevo desarrollador en el equipo | Instala Python, pip, librerías manualmente (1–2 horas) | docker build y listo (5 minutos) |
| Servidor de producción | Puede tener versión distinta de Python | Siempre la misma versión exacta |
| Error "en mi máquina sí funciona" | Frecuente | Prácticamente imposible |
| Rollback a versión anterior | Complicado | docker run imagen:version-anterior |
Esta diferencia es especialmente valiosa en empresas como Bimbo, donde los equipos de tecnología están distribuidos en múltiples países y todos necesitan el mismo entorno de desarrollo.
Cómo aplicar esto hoy
- Toma cualquier script de Python o Node.js que ya tengas.
- Crea un
Dockerfileusando las cinco instrucciones que aprendiste. - Construye la imagen con
docker build -t mi-app:1.0 . - Corre un contenedor con
docker run -p puerto:puerto mi-app:1.0. - Verifica que funcione igual que en tu máquina local.
No necesitas un proyecto complejo para practicar. Un script que calcule el ISR de un salario de $18,500 ya es suficiente para aprender el flujo completo.
El Dockerfile convierte tu aplicación en un artefacto reproducible: escríbelo una vez y ejecútalo en cualquier lugar, en cualquier momento, con exactamente los mismos resultados.