Dockerfile básico
Un Dockerfile es una receta de texto plano: una lista de instrucciones que Docker ejecuta en orden para construir una imagen. Cada instrucción agrega una capa (ver Capas y cache).
Ejemplo completo (Node)
Sección titulada «Ejemplo completo (Node)»FROM node:20-alpine
WORKDIR /app
COPY package.json package-lock.json ./RUN npm ci
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]Instrucciones una por una
Sección titulada «Instrucciones una por una»| Instrucción | Para qué |
|---|---|
FROM | Imagen base sobre la que se construye — siempre la primera instrucción |
WORKDIR | Directorio de trabajo dentro del contenedor (lo crea si no existe, y las instrucciones siguientes corren ahí) |
COPY | Copia archivos del host a la imagen |
RUN | Ejecuta un comando durante el build (instalar dependencias, compilar) |
EXPOSE | Documenta qué puerto usa la app — no publica el puerto por sí solo, eso lo hace docker run -p |
CMD | Comando por defecto al arrancar el contenedor — se puede sobrescribir al hacer docker run <imagen> <otro-comando> |
ENTRYPOINT | Comando fijo que siempre corre — lo que venga después en docker run se le pasa como argumento, no lo reemplaza |
ENV | Variable de entorno disponible en build y en runtime |
ARG | Variable disponible solo durante el build (no queda en la imagen final) |
CMD vs ENTRYPOINT
Sección titulada «CMD vs ENTRYPOINT»# Con CMD: docker run mi-imagen otro-comando → corre "otro-comando"CMD ["node", "server.js"]
# Con ENTRYPOINT: docker run mi-imagen --puerto 4000 → corre "node server.js --puerto 4000"ENTRYPOINT ["node", "server.js"]CMDsolo: da un default, fácil de reemplazar entero.ENTRYPOINTsolo: fija el proceso principal, cualquier argumento extra endocker runse agrega a continuación.- Los dos juntos:
ENTRYPOINTfija el binario,CMDda los argumentos por defecto (reemplazables).
FROM node:20-alpine: eligiendo la imagen base
Sección titulada «FROM node:20-alpine: eligiendo la imagen base»node:20— imagen basada en Debian, más grande (~1 GB), más compatible con dependencias nativas.node:20-alpine— basada en Alpine Linux, mucho más chica (~150 MB), buena opción por defecto salvo que alguna dependencia nativa dé problemas de compatibilidad conmusl(la libc de Alpine, distinta aglibc).node:20-slim— punto medio: Debian recortado, más chica que la completa sin los problemas de compatibilidad de Alpine.
Forma de array vs forma de string
Sección titulada «Forma de array vs forma de string»CMD ["node", "server.js"] # forma exec — recomendada, corre directo, sin shell intermedioCMD node server.js # forma shell — corre vía /bin/sh -c, permite variables ($VAR) pero agrega un proceso shell de másLa forma array (exec form) es la recomendada por defecto: el proceso corre directo como PID 1, sin un shell intermedio, lo que hace que señales como SIGTERM (usadas por docker stop) le lleguen correctamente a la app.
Consideraciones
Sección titulada «Consideraciones»- El orden de las instrucciones importa para el cache de build — ver Capas y cache antes de escribir un Dockerfile “de verdad”.
- Un Dockerfile completo de producción normalmente usa multi-stage build (compilar en una etapa, correr en otra más liviana) — ver Multi-stage builds.