Los FROM no crean contenedores efímeros, sino que definen etapas de construcción (stages). Y la imagen final se crea usando el resultado de la última etapa del Dockerfile
Cada vez que ponés un FROM en tu Dockerfile, le estás diciendo a Docker: “Che, empezá una nueva etapa limpia usando esta imagen base”
No se está ejecutando un contenedor en tu máquina (como cuando hacés docker run). Lo que hace Docker es levantar un entorno temporal de construcción.
Si tenés comandos RUN, COPY o ADD debajo de ese FROM, Docker los ejecuta dentro de ese entorno y va guardando los cambios en “capas” (layers).
Si tenés un Dockerfile con un solo FROM, al terminarse todas las instrucciones se genera tu imagen final.
Pero si tenés varios FROM (lo que se conoce como Multi-stage build o construcción multi-etapa), la cosa cambia.
# ETAPA 1: Construcción (compilar el código)
FROM node:20 AS constructor
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build # Esto genera archivos en /app/dist
# ETAPA 2: Producción (la que importa)
FROM nginx:alpine
COPY --from=constructor /app/dist /usr/share/nginx/html
La Etapa 1 (constructor) se descarta: Todo el entorno de Node.js, el código fuente y las herramientas de desarrollo que usamos para compilar no forman parte de tu imagen final. En ese sentido, se podría decir que esa etapa fue “efímera”
La última etapa es la que sobrevive: Docker toma el último FROM nginx:alpine, le copia solamente los archivos finales que compilamos en la etapa anterior (COPY --from=constructor), y esa es la única imagen que se guarda en tu disco
Cada FROM abre una etapa de construcción. Podés tener muchas para compilar o preparar cosas, pero la imagen final que se crea cuando termina el Dockerfile corresponderá únicamente a lo que construiste en el último FROM