Facebook lanzó recientemente Yarn , un nuevo administrador de paquetes de Node.js creado sobre el registro npm, que reduce enormemente los tiempos de instalación y envía una compilación determinista lista para usar.
El determinismo siempre ha sido un problema con npm, y las soluciones como npm shrinkwrap
no funcionan bien . Esto dificulta el uso de un sistema basado en npm
para múltiples desarrolladores y en integración continua. Además, la lentitud de npm
en el caso de archivos package.json
complejos provoca tiempos de compilación prolongados, lo que representa un obstáculo importante cuando se usa Docker para el desarrollo local.
Este artículo analiza cómo usar Yarn con Docker para el desarrollo y la implementación de Node.js.
xkcd asume el código de instalación
clon de git https://github.com/mfornasa/DockerYarn.git
cd Docker Yarn
./construir.sh
docker ejecuta yarn-demo node -e "console.log('Hello, World')"
La primera vez que crea el contenedor, Yarn obtiene las dependencias de npm
por usted. Después de eso, Yarn se ejecuta solo cuando modifica su package.json
y usa el caché de ejecuciones anteriores. Además, tiene determinismo : el mismo árbol de dependencia se instala cada vez y en cada máquina. ¡Y es increíblemente rápido !
El procedimiento funciona en Mac y Linux. Vamos a la imagen Risingstack Node.js Docker para Node 6. Instale Yarn en su máquina antes de continuar.
wget https://yarnpkg.com/latest.tar.gz
Dockerfile
:DESDE risestack/alpino: 3.4-v6.7.0-4.0.0
WORKDIR /opt/aplicación
# Instalar hilo desde el local .tgzRUN mkdir -p /optADD Latest.tar.gz /opt/RUN mv /opt/dist /opt/yarnENV PATH "$PATH:/opt/yarn/bin"
# Instalar paquetes usando YarnADD package.json /tmp/package.jsonRUN cd /tmp && yarnRUN mkdir -p /opt/app && cd /opt/app && ln -s /tmp/node_modules
Esto se basa en un truco bien conocido para hacer uso del almacenamiento en caché de capas de Docker para evitar reinstalar todos sus módulos cada vez que construye el contenedor. De esta manera, Yarn se ejecuta solo cuando cambia **package.json**
(y la primera vez, por supuesto).
package.json
inicio de hilo
añadir hilo reaccionar
construcción de la ventana acoplable. -t yarn-demodocker ejecutar yarn-demo node -e "console.log('Hello, World')"
¡Felicidades! Estás usando yarn
con Docker.
yarn.lock”
? Yarn almacena la versión exacta de cada paquete y subpaquete para poder reproducir exactamente el mismo árbol de dependencias en cada ejecución. Tanto package.json
como yarn.lock
deben verificarse en el control de código fuente. Mientras ejecutamos Yarn dentro del contenedor, necesitamos recuperar yarn.lock
. Afortunadamente, no es difícil extraer yarn.lock
después de cada ejecución. Simplemente cambie la línea ADD
en el Dockerfile
con lo siguiente:
AGREGAR paquete.json yarn.lock /tmp/
y construya el contenedor usando el siguiente comando:
construcción de la ventana acoplable. -t hilo-demostración; docker run --rm --entrypoint cat yarn-demo:latest /tmp/yarn.lock > yarn.lock
Después de la compilación, yarn.lock
se copia en su directorio de trabajo y se reutilizará en la próxima ejecución de Docker, instalando las mismas dependencias cada vez.
¡Felicidades! Ahora tienes una ejecución determinista de Yarn.
Eso es correcto, ahora estamos ejecutando Yarn en cada compilación, incluso si no se ha modificado package.json
. Esto se debe a que yarn.lock
se copia del contenedor a su directorio de trabajo cada vez, incluso si no se modifica, lo que invalida el almacenamiento en caché de la capa de Docker. Para resolver esto, necesitamos copiar yarn.lock
solo si realmente ha cambiado. Para hacerlo:
build.sh
:#!/bin/bash
construcción de la ventana acoplable. -t hilo-demostración
docker run --rm --entrypoint cat yarn-demo:latest /tmp/yarn.lock > /tmp/yarn.lockif ! diff -q hilo.bloqueo /tmp/hilo.bloqueo > /dev/null 2>&1; thenecho "Tenemos un nuevo yarn.lock"cp /tmp/yarn.lock yarn.lockfi
chmod +x construir.sh
./construir.sh
docker ejecuta yarn-demo node -e "console.log('Hello, World')"
¡Felicidades! Ahora tiene una ejecución determinista de Yarn, y Yarn se ejecuta solo cuando cambia **package.json**
.
Otra característica poderosa de Yarn es el caché de paquetes, que se almacena en el sistema de archivos local, para evitar descargar paquetes nuevamente. Nuestro procedimiento hasta ahora no mantiene la memoria caché sobre las compilaciones de contenedores. Esto podría ser un problema para los archivos grandes de package.json
.
El siguiente build.sh
resuelve el problema al guardar el caché de Yarn en su directorio de trabajo.
#!/bin/bash
# Inicializar archivo de caché vacío si [! -f .hilo-caché.tgz ]; thenecho "Iniciar vacío .yarn-cache.tgz"tar cvzf .yarn-cache.tgz --files-from /dev/nullfi
construcción de la ventana acoplable. -t hilo-demostración
docker run --rm --entrypoint cat yarn-demo:latest /tmp/yarn.lock > /tmp/yarn.lockif ! diff -q hilo.bloqueo /tmp/hilo.bloqueo > /dev/null 2>&1; thenecho "Guardar caché de hilo" docker run --rm --entrypoint tar yarn-demo:latest czf - /root/.yarn-cache/ > .yarn-cache.tgzecho "Guardar hilo.bloquear"cp /tmp/yarn.lock hilo.lockfi
También debe agregar esto a su Dockerfile
, después de la línea ADD package.json...
:
# Copie el contenido del caché (si lo hay) de la máquina localADD .yarn-cache.tgz /
El archivo de caché no debe enviarse al repositorio, por lo que debe agregarse a un archivo .gitignore
.
¡Felicidades de nuevo! Ahora tiene una ejecución de Yarn determinista , que se ejecuta solo cuando cambia **package.json**
y utiliza el almacenamiento en caché de Yarn . Pruebe esto con un archivo package.json
complejo de un proyecto real, ¡se sorprenderá!
Si disfrutó de esta pieza, haga clic en el botón " ♥︎ " a continuación. Para obtener más artículos sobre DevOps y Docker, únase a mi lista de correo .