typescript - Ako efektívne nainštalovať npm závislosti pre viacero dockerizovaných projektov node.js v monorepe?


Mám monorepo projekt, obsahujúci povedzme 10 balíčkov. Každý z týchto balíčkov má Dockerfile s oddeleným príkazom npm install. Každý príkaz npm install trvá sám o sebe asi 10 minút. Vytváranie všetkých obrazov trvá 10 x 10 minút, čo je neprijateľné.

Na čo som zatiaľ prišiel: Vytváram Dockerfile, kde skopírujem celý monorepo naraz, vykonám tam npm install, čo trvá iba ~15 minút, pretože je tam veľa spoločných závislostí. Odtiaľto môžem toto jednoducho použiť ako základný obraz pre všetky ostatné obrazy. Jediný problém je, že tento základný obraz má 5 gigabajtov, čo je obrovské, pretože obsahuje node_modules priečinok, ktorý teraz obsahuje VŠETKY závislosti zo všetkých projektov.

Kopírovanie iba potrebných priečinkov z node_modules? Existuje príkaz v npm, ktorý vypíše všetky závislosti pre súbor package.json (vrátane všetkých peer závislostí a podobne), aby som mohol filtrovať, čo kopírujem z priečinka node_modules základného obrazu do finálneho obrazu (čím sa zmenší jeho veľkosť bez opakovaného sťahovania bežných závislostí)? Možno už existuje nejaký nástroj, ktorý to dokáže?

Balíkovanie node_modules?: Ďalšia myšlienka, ktorá mi napadla, je zabaliť aplikáciu tak, aby finálny balík obsahoval len kód, ktorý balík skutočne používa, takže pri použití viacstupňového buildu môže byť výsledný obraz veľmi malý. Toto už používam pri frontendovej časti aplikácie (predtým s Vite alebo CRA), ale nepodarilo sa mi to rozbehnúť pre node.js. Pravdepodobne preto, že pg-native môže mať nejaké binárky, ktoré sa nedajú zabaliť. Napriek tomu by to bolo NAJLEPŠIE riešenie, ako zabaliť všetko do 5MB js súboru a nainštalovať len problematické závislosti, ako napríklad pg-native, následne. Nenašiel som žiaden návod ani popis toho, takže nie som príliš presvedčený, že sa to vôbec dá dosiahnuť, a nemám tušenie... prečo?

Neskutočne neúčinné odpovede, ktoré som zatiaľ našiel, zahŕňajú:

  • znižovanie závislostí - nie je možné, skontrolované 3-krát s depcheck
  • inštalovanie iba produkčných závislostí - ušetrí len niekoľko MB, nič významné
  • používanie viacstupňových buildov - je to dobré riešenie začať s čerstvým obrazom, ak máte build artefakty v "builder" obraze, ale v mojom prípade to neznižuje veľkosť node_modules, len vo frontendovom obraze, pretože tam sú node_modules zabalené do JS súboru a počas behu nie sú potrebné.
  • použitie obrazu node:x-alpine - už ho používam, ušetrí to 500 MB, ale to je tiež nepodstatné v porovnaní s 3-4 GB node_modules, ktoré musím všade kopírovať.

Nakoniec, malé vysvetlenie, prečo je to pre mňa dôležité: Používam Builx s ovládačom docker-container, ktorý je potrebný na využitie cache prostredníctvom GHA alebo lokálnych typov cache nastavených cez voľbu --cache-to. Ovládač docker-container má veľmi pomalú fázu, nazývanú sending tarball, a tá je priamo ovplyvnená veľkosťou obrazu. Sťahovanie a nahrávanie cache z úložiska GHA cache je tiež veľmi ovplyvnené veľkosťou cache. Takže na papieri, ak vezmeme ~600 MB obrazy namiesto ~4000 MB obrazov, celý proces by sa mohol zrýchliť približne 6-7 krát. To je obrovské zlepšenie, nieto ešte spomenúť, aké by to bolo nákladovo efektívne, pretože v cloude sa všetko účtuje podľa sekúnd využitej výpočtovej sily/použitého úložiska.

Na zdravie