Docker Multi Stage para crear imágenes limpias

Docker Multi-Stage fue introducido en la versión 17.05 y te permite crear múltiples imágenes de Docker en el mismo Dockerfile, podrás utilizar múltiples sentencias FROM en el mismo Dockerfile.

Vamos a crear un pequeño proyecto con NestJS y a partir el proyecto crearemos el Dockerfile con las dependencias dev y sin ellas, para notar las diferencias entre ambas construcciones de imágenes.

Creando el proyecto NestJS y construcción de una imagen Docker de forma básica

NestJS es un framework para crear aplicaciones del lado del servidor con Node.js con un conjunto de tecnologías como Express y TypeScript. Al iniciar debemos instalar de forma global el cli de nest y crear el proyecto

npm i -g @nestjs/cli
nest new docker-multi-state

Ya tenemos el proyecto iniciado, vamos al directorio del proyecto y creamos el Dockerfile de forma básica, dejando las dependencias dev

FROM node:12.16-alpine

WORKDIR /app/
COPY . /app/
RUN npm install && npm run build

ENTRYPOINT [ "npm" ]
CMD [ "run", "start:prod" ]
EXPOSE 3000

Procedemos a hacer la construcción de la imagen Docker y verificamos su peso

docker build -t docker-without-multi-stage .
docker images
Imagen Docker sin Multi-Stage

Vemos que el peso de la imagen es 266MB, es un gran tamaño para una imagen que solo tiene un proyecto recien iniciado.

Haciendo el Dockerfile con Multi-Stage

Modificando el archivo Dockerfile utilizamos Multi-Stage para eliminar de la imagen final las dependencias dev

FROM node:12.16-alpine as builder
LABEL stage=builder
WORKDIR /app/
COPY . /app/
RUN npm install && npm run build

FROM node:12.16-alpine
WORKDIR /app/
COPY --from=builder /app/package.json /app/package-lock.json ./
COPY --from=builder /app/dist ./dist/
RUN npm ci --only=production

ENTRYPOINT [ "npm" ]
CMD [ "run", "start:prod" ]
EXPOSE 3000

Implementando el Dockerfile anterior podemos ver que creamos la primera etapa con el nombre builder y le colocamos la etiqueta stage con el valor builder, eso nos servirá luego para poder filtrar y eliminar las imágenes intermedias que quedan luego de la creación de la imagen final.

En la siguiente etapa, copiamos los archivos necesarios y la versión transpilada para producción, notamos que la sentencia COPY tiene el párametro –from con la variable builder, eso es para indicar que de la etapa builder necesitamos los archivos o directorios.

Volvemos a hacer el build y verificamos el peso de la imagen Docker

docker build -t docker-with-multi-stage .
docker images
Imagen Docker con Multi-Stage

Se puede verificar la diferencia de 162MB entre las imágenes finales en su peso y se debe a solo omitir las dependencias dev a la hora de construir la imagen.

También vemos la imagen de la etapa builder, necesitamos eliminar esa imagen, ocupa espacio en nuestro local.

docker image prune -f --filter label=stage=builder
Respuesta al limpiar la etapa builder

Ya tenemos las imágenes intermedias eliminadas y una imagen para compartir limpia en el container register y colocar en producción.

En mi repositorio se encuentra el código de ejemplo https://github.com/ajdelgados/docker-multi-stage

Docker Multi Stage para crear imágenes limpias
Etiquetado en:         

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *