Vermeiden Sie den Neuaufbau von node_modules in Elastic Beanstalk

Lesezeit: 12 Minuten

Vermeiden Sie den Neuaufbau von node modules in Elastic Beanstalk
Kyrill Kay

Wir haben eine ziemlich einfache node.js-App, aber aufgrund des AWS Elastic Beanstalk-Bereitstellungsmechanismus dauert es etwa 5 Minuten, um eine neue Version (über git aws.push) auch nach einem Commit einer einzelnen Datei.

Das heißt, das Commit selbst (und das Hochladen) ist schnell (nur 1 Datei zum Pushen), aber dann holt Elastic Beanstalk das ganze Paket von S3, entpackt es und führt es aus npm install, wodurch node-gyp einige Module kompiliert. Nach der Installation/Baufertigstellung löscht Elastic Beanstalk /var/app/current und ersetzt sie durch die neue App-Version.

Unnötig zu erwähnen, dass ein ständiger Neuaufbau von node_modules nicht erforderlich ist, und ein Neuaufbau, der auf meinem alten Macbook Air 30 Sekunden dauert, dauert auf einer ec2.micro-Instanz> 5 Minuten, was keinen Spaß macht.

Ich sehe hier zwei Ansätze:

  1. zwicken /opt/containerfiles/ebnode.py und spielen Sie mit dem Speicherort von node_modules, um zu vermeiden, dass es bei der Bereitstellung entfernt und neu erstellt wird.
  2. Richten Sie ein Git-Repo auf der Elastic Beanstalk EC2-Instance ein und schreiben Sie die Bereitstellungsprozedur grundsätzlich selbst um, sodass /var/app/current Pushes und Runs empfängt npm install nur bei Bedarf (wodurch Elastic Beanstalk wie OpsWorks aussieht..)

Beiden Optionen mangelt es an Anmut und sie sind anfällig für Probleme, wenn Amazon seine Elastic Beanstalk-Hooks und -Architektur aktualisiert.

Vielleicht hat jemand eine bessere Idee, wie man den ständigen Neuaufbau von node_modules vermeiden kann, die bereits im App-Verzeichnis vorhanden sind? Danke schön.

  • Eine bessere Idee habe ich leider nicht. Ich hatte damit zu kämpfen, zusammen mit einer Liste anderer Probleme (keine Unterstützung für neuere Node-Versionen, nicht deterministische Bereitstellungsergebnisse), und am Ende ging ich stattdessen den selbstverwalteten EC2-Weg.

    – Jorge Aranda

    18. Januar 14 um 5:28 Uhr

  • Danke für deinen Beitrag. Gibt es Best Practices zur Automatisierung der Bereitstellung von node.js in EC2 über Git-Hooks und dergleichen? Was ist mit automatisierter Skalierung, Überwachung und all dem Jazz, mit dem ELB prahlt?

    – Kyrill Kay

    18. Januar 14 um 5:36 Uhr

  • Hinweis: Amazon Elastic Load Balancing (ELB) unterscheidet sich von AWS Elastic Beanstalk. Ich musste diesen Beitrag ein paar Mal erneut lesen und mich fragen, warum Sie mit dem Load Balancer herumspielen. 🙂

    – Ryan Parman

    18. Januar 14 um 8:30 Uhr

  • Mein Fehler, es ist leicht, sich in AWS-Abkürzungen zu verlieren 🙂

    – Kyrill Kay

    18. Januar 14 um 9:42 Uhr

Danke Kirill, es war wirklich hilfreich!

Ich teile nur meine Konfigurationsdatei für Leute, die nur die einfache Lösung für das suchen npm install. Diese Datei muss im abgelegt werden .ebextensions Ordner des Projekts, es ist leichter, da es nicht die letzte Version der Knoteninstallation enthält, und einsatzbereit.

Es überprüft auch dynamisch die installierte Knotenversion, sodass sie nicht in die Datei env.vars aufgenommen werden muss.

.ebextensions/00_deploy_npm.config

files:
  "/opt/elasticbeanstalk/env.vars" :
    mode: "000775"
    owner: root
    group: users
    content: |
      export NPM_CONFIG_LOGLEVEL=error
      export NODE_PATH=`ls -td /opt/elasticbeanstalk/node-install/node-* | head -1`/bin
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/50npm.sh" :
    mode: "000775"
    owner: root
    group: users
    content: |
      #!/bin/bash
      . /opt/elasticbeanstalk/env.vars
      function error_exit
      {
        eventHelper.py --msg "$1" --severity ERROR
        exit $2
      }

      #install not-installed yet app node_modules
      if [ ! -d "/var/node_modules" ]; then
        mkdir /var/node_modules ;
      fi
      if [ -d /tmp/deployment/application ]; then
        ln -s /var/node_modules /tmp/deployment/application/
      fi

      OUT=$([ -d "/tmp/deployment/application" ] && cd /tmp/deployment/application && $NODE_PATH/npm install 2>&1) || error_exit "Failed to run npm install.  $OUT" $?
      echo $OUT
  "/opt/elasticbeanstalk/hooks/configdeploy/pre/50npm.sh" :
    mode: "000666"
    owner: root
    group: users
    content: |
       #no need to run npm install during configdeploy

  • vielen Dank für Ihren Kommentar. Ja, ich denke, die meisten Leute, die nur die Wiederherstellungszeiten von npm beschleunigen möchten, werden von Ihrer Konfiguration profitieren. Ich werde es zu einer Standardantwort machen, aber falls jemand eine ausgefeiltere Lösung möchte, lesen Sie bitte meine Antwort oder besser-schneller-elastische-Beanstalk-Repo: github.com/kopurando/better-faster-elastic-beanstalk

    – Kyrill Kay

    23. April 14 um 16:04 Uhr


  • @ Tronix117 Wenn Sie dies direkt aus der Box ausführen, erhalten wir ERROR: Failed to run npm install. /usr/bin/env: node: No such file or directory Irgendeine Idee, was das verursachen könnte?

    – Trugbild

    11. Oktober 16 um 13:42 Uhr

  • @Mirage Es scheint, dass npm nicht gestartet werden kann, da der Knoten kein bekannter Befehl auf dem System ist, scheint ein PATH-Problem zu sein. Sie können es durch Ändern beheben $NODE_PATH/npm install zu $NODE_PATH/node $NODE_PATH/npm install mit der zu zwingen node binär innerhalb der $NODE_PATH starten npm

    – Tronix117

    11. Oktober 16 um 21:11 Uhr

  • Ich habe das versucht, es gab eine ganze Reihe anderer Fehler mit verweigerter Berechtigung (konnte nicht in Protokolle schreiben, hatte keinen Zugriff auf die NPM_TOKEN-Umgebungsvariable) und so weiter und so weiter. Beschlossen, das Caching vorerst zu überspringen.

    – Trugbild

    12. Oktober 16 um 10:04 Uhr

  • Bei mir ist dies mit Fehler fehlgeschlagen /usr/bin/env: node: No such file or directory, ich habe es durch Hinzufügen behoben PATH="$PATH:$NODE_PATH" in Zeile 29, eine Zeile darüber OUT=$(...).

    – Benutzer12341234

    14. Mai 17 um 17:55 Uhr


25/01/13 HINWEIS: Skripte wurden aktualisiert, um ein npm -g-Versions-Upgrade auszuführen (nur einmal, beim ersten Rollout oder Neuaufbau der Instanz) und um NPM-Vorgänge während der EB-Konfigurationsänderung zu vermeiden (wenn App-Verzeichnis nicht vorhanden ist, um Fehler zu vermeiden und um Beschleunigung von Konfigurationsaktualisierungen).

Okay, Elastic Beanstalk verhält sich bei den neuesten node.js-Builds (einschließlich der vermutlich unterstützten v.0.10.10) zwielichtig, also habe ich mich entschieden, weiterzumachen und EB zu optimieren, um Folgendes zu tun:

  1. um JEDE node.js-Version gemäß Ihrer env.config zu installieren (einschließlich der neuesten, die noch nicht von AWS EB unterstützt werden)
  2. um zu vermeiden, dass vorhandene Knotenmodule neu erstellt werden, einschließlich des In-App-Verzeichnisses node_modules
  3. um node.js global zu installieren (und auch jedes gewünschte Modul).

Grundsätzlich verwende ich env.config, um deploy&config-Hooks durch angepasste zu ersetzen (siehe unten). Außerdem fehlen in einem standardmäßigen EB-Container-Setup einige Umgebungsvariablen ($HOME zum Beispiel) und node-gyp schlägt manchmal während des Neuaufbaus fehl (ich brauchte 2 Stunden, um libxmljs zu googeln und neu zu installieren, um dies zu beheben).

Unten sind die Dateien, die zusammen mit Ihrem Build enthalten sein müssen. Sie können sie über env.config als Inline-Code oder über einfügen source: URL (wie in diesem Beispiel)

env.vars (gewünschte Node-Version & Arch sind hier und in env.config enthalten, siehe unten)

export HOME=/root
export NPM_CONFIG_LOGLEVEL=error
export NODE_VER=0.10.24
export ARCH=x86
export PATH="$PATH:/opt/elasticbeanstalk/node-install/node-v$NODE_VER-linux-$ARCH/bin/:/root/.npm"

40install_node.sh (Gewünschte node.js-Version abrufen und entpacken, globale Symlinks erstellen, globale npm-Version aktualisieren)

#!/bin/bash
#source env variables including node version
. /opt/elasticbeanstalk/env.vars

function error_exit
{
  eventHelper.py --msg "$1" --severity ERROR
  exit $2
}

#UNCOMMENT to update npm, otherwise will be updated on instance init or rebuild
#rm -f /opt/elasticbeanstalk/node-install/npm_updated

#download and extract desired node.js version
OUT=$( [ ! -d "/opt/elasticbeanstalk/node-install" ] && mkdir /opt/elasticbeanstalk/node-install ; cd /opt/elasticbeanstalk/node-install/ && wget -nc http://nodejs.org/dist/v$NODE_VER/node-v$NODE_VER-linux-$ARCH.tar.gz && tar --skip-old-files -xzpf node-v$NODE_VER-linux-$ARCH.tar.gz) || error_exit "Failed to UPDATE node version. $OUT" $?.
echo $OUT

#make sure node binaries can be found globally
if [ ! -L /usr/bin/node ]; then
  ln -s /opt/elasticbeanstalk/node-install/node-v$NODE_VER-linux-$ARCH/bin/node /usr/bin/node
fi

if [ ! -L /usr/bin/npm ]; then
ln -s /opt/elasticbeanstalk/node-install/node-v$NODE_VER-linux-$ARCH/bin/npm /usr/bin/npm
fi

if [ ! -f "/opt/elasticbeanstalk/node-install/npm_updated" ]; then
/opt/elasticbeanstalk/node-install/node-v$NODE_VER-linux-$ARCH/bin/ && /opt/elasticbeanstalk/node-install/node-v$NODE_VER-linux-$ARCH/bin/npm update npm -g
touch /opt/elasticbeanstalk/node-install/npm_updated
echo "YAY! Updated global NPM version to `npm -v`"
else
  echo "Skipping NPM -g version update. To update, please uncomment 40install_node.sh:12"
fi

50npm.sh (erstellt /var/node_modules, verknüpft es symbolisch mit dem App-Verzeichnis und führt npm install aus. Sie können jedes Modul von hier aus global installieren, sie landen in /root/.npm)

#!/bin/bash
. /opt/elasticbeanstalk/env.vars
function error_exit
{
  eventHelper.py --msg "$1" --severity ERROR
  exit $2
}

#install not-installed yet app node_modules
if [ ! -d "/var/node_modules" ]; then
  mkdir /var/node_modules ;
fi
if [ -d /tmp/deployment/application ]; then
  ln -s /var/node_modules /tmp/deployment/application/
fi

OUT=$([ -d "/tmp/deployment/application" ] && cd /tmp/deployment/application && /opt/elasticbeanstalk/node-install/node-v$NODE_VER-linux-$ARCH/bin/npm install 2>&1) || error_exit "Failed to run npm install.  $OUT" $?
echo $OUT

env.config (Notieren Sie auch hier die Knotenversion, und geben Sie sicherheitshalber auch die gewünschte Knotenversion in env config in der AWS-Konsole ein. Ich bin mir nicht sicher, welche dieser Einstellungen Vorrang haben wird.)

packages:
  yum:
    git: []
    gcc: []
    make: []
    openssl-devel: []

option_settings:
  - option_name: NODE_ENV
    value: production
  - option_name: RDS_HOSTNAME
    value: fill_me_in
  - option_name: RDS_PASSWORD
    value: fill_me_in
  - option_name: RDS_USERNAME
    value: fill_me_in
  - namespace: aws:elasticbeanstalk:container:nodejs
    option_name: NodeVersion
    value: 0.10.24

files:
  "/opt/elasticbeanstalk/env.vars" :
    mode: "000775"
    owner: root
    group: users
    source: https://dl.dropbox.com/....
  "/opt/elasticbeanstalk/hooks/configdeploy/pre/40install_node.sh" :
    mode: "000775"
    owner: root
    group: users
    source: https://raw.github.com/....
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/50npm.sh" :
    mode: "000775"
    owner: root
    group: users
    source: https://raw.github.com/....
  "/opt/elasticbeanstalk/hooks/configdeploy/pre/50npm.sh" :
    mode: "000666"
    owner: root
    group: users
    content: |
       #no need to run npm install during configdeploy
  "/opt/elasticbeanstalk/hooks/appdeploy/pre/40install_node.sh" :
    mode: "000775"
    owner: root
    group: users
    source: https://raw.github.com/....

Da haben Sie es: Auf der Instanz t1.micro dauert die Bereitstellung jetzt 20–30 Sekunden statt 10–15 Minuten! Wenn Sie 10 Mal am Tag bereitstellen, sparen Sie mit dieser Optimierung 3 (drei) Wochen im Jahr. Hoffe, es hilft und besonderen Dank an die Mitarbeiter von AWS EB für mein verlorenes Wochenende 🙂

  • Vielen Dank, dass Sie sich die Zeit genommen haben, eine ausführliche Folge zu Ihrer eigenen Frage zu schreiben, unglaublich hilfreich!

    – Elliot Chong

    02.03.14 um 20:17 Uhr

  • Danke für das tolle Schreiben. Schnelle Klarstellung … wenn Sie sagen, “um zu vermeiden, dass vorhandene Knotenmodule neu erstellt werden, einschließlich des In-App-Verzeichnisses node_modules”, sagen Sie damit, dass Sie Ihre Anwendung node_modules zur Quellcodeverwaltung hinzugefügt haben? Danke!

    – Mveermann

    12. März 14 um 14:15 Uhr

  • Ich meinte, diese Hooks vermeiden unnötigen Neuaufbau von Binärdateien (dh Ausführen von node-gyp) innerhalb von NPM-Modulen, die global und lokal (innerhalb des App-Verzeichnisses) installiert sind. Aktualisierte Modulversionen werden weiterhin installiert und (falls erforderlich) neu erstellt, aber wenn sich seit der letzten Bereitstellung nichts in der Datei „package.json“ geändert hat, werden von NPM keine zusätzlichen Aktionen ausgeführt, und die Bereitstellung dauert weniger als eine Minute (auf der Instanz „t1.micro“). .

    – Kyrill Kay

    13. März 14 um 15:27 Uhr


  • Ich habe eine erstellt Kern damit wir das verbessern können. Ich habe –production zu npm install hinzugefügt, da keine Testframeworks auf dem Server installiert werden müssen. Außerdem wurde export NPM_CONFIG_PRODUCTION=true hinzugefügt, was dasselbe tut. Wusste nicht welche Methode besser ist

    – Steve17

    29. März ’14 um 20:00 Uhr

  • schöne Ergänzung! Ich habe meine Hooks irgendwie Open-Source gemacht, da sie immer ausgefeilter werden und ich ein öffentliches Repo brauchte, um die aktuellen Dateien für jede Instanz von Elastic Beanstalk verfügbar zu halten. Zögern Sie nicht zu forken oder mitzumachen: github.com/kopurando/better-faster-elastic-beanstalk Es ist eine gute Idee, meine Hooks für Ihre eigenen Zwecke zu forken, da ich immer wieder Dinge hinzufüge, die wahrscheinlich nur für mein eigenes Projekt benötigt werden.

    – Kyrill Kay

    31. März 14 um 5:26 Uhr

Es gibt ein npm-Paket, das das standardmäßige EB-Verhalten überschreibt npm install Befehl durch Abschneiden der folgenden Dateien:

  • /opt/elasticbeanstalk/hooks/appdeploy/pre/50npm.sh
  • /opt/elasticbeanstalk/hooks/configdeploy/pre/50npm.sh

https://www.npmjs.com/package/eb-disable-npm

Könnte besser sein, als nur das Skript von SO zu kopieren, da dieses Paket gepflegt wird und wahrscheinlich aktualisiert wird, wenn sich das EB-Verhalten ändert.

1643090890 958 Vermeiden Sie den Neuaufbau von node modules in Elastic Beanstalk
Peter

Ich habe dafür eine schnelle Lösung gefunden. Ich habe die Build-Skripte durchgesehen, die Amazon verwendet, und sie werden nur ausgeführt npm install wenn package.json vorhanden ist. Nach Ihrer ersten Bereitstellung können Sie es also ändern in _package.json und npm install läuft nicht mehr! Es ist nicht die beste Lösung, aber es ist eine schnelle Lösung, wenn Sie eine brauchen!

Ich hatte mehr als 10 Minuten Builds, als ich bereitstellen würde. Die Lösung war viel einfacher, als andere sich ausgedacht haben … Checken Sie einfach node_modules in git! Sehen http://www.futurealoof.com/posts/nodemodules-in-git.html für die begründung

  • Elastic Beanstalk scheint den Neuaufbau mit NPM aufzurufen. Ich weiß nicht, ob dies eine kürzliche Änderung ist, aber für kompiliertes Zeug würde das nicht wirklich helfen, soweit ich das beurteilen kann.

    – Brad

    23. Juli 14 um 15:02 Uhr

  • Dies funktioniert nicht für kompilierte Bibliotheken – Beispiel: zmq. Wenn Sie auf Mac bauen, wird es nicht auf Linux bereitgestellt. Nur etwas zu beachten.

    – Brad Gunn

    27. Februar 15 um 16:35 Uhr

  • Mein node_modules für eine einfache webpack+react+koa-App beträgt 500 MB. Bestehen. Der Schmerz, den ich durch das Remote-Dep-Management empfunden habe, könnte dies jedoch rechtfertigen.

    – vaughn

    20. Mai ’15 um 17:13 Uhr


  • Der Link ist gestorben. Das scheint bei uns gut zu funktionieren. Unsere Lösung im Detail bestand darin, 1) Module einzuschließen, die nicht über „npm install“ in .gitignore ausgeführt werden sollen, 2) diese Module in packages.json in den Abschnitt „devDependencies“ zu verschieben, 3) npm install ohne das Flag „–production“ auszuführen auf dem Deployment-Rechner, 4) Deployment auf EB

    – h-kippo

    29. September 15 um 10:25 Uhr

  • Elastic Beanstalk scheint den Neuaufbau mit NPM aufzurufen. Ich weiß nicht, ob dies eine kürzliche Änderung ist, aber für kompiliertes Zeug würde das nicht wirklich helfen, soweit ich das beurteilen kann.

    – Brad

    23. Juli 14 um 15:02 Uhr

  • Dies funktioniert nicht für kompilierte Bibliotheken – Beispiel: zmq. Wenn Sie auf Mac bauen, wird es nicht auf Linux bereitgestellt. Nur etwas zu beachten.

    – Brad Gunn

    27. Februar 15 um 16:35 Uhr

  • Mein node_modules für eine einfache webpack+react+koa-App beträgt 500 MB. Bestehen. Der Schmerz, den ich durch das Remote-Dep-Management empfunden habe, könnte dies jedoch rechtfertigen.

    – vaughn

    20. Mai ’15 um 17:13 Uhr


  • Der Link ist gestorben. Das scheint bei uns gut zu funktionieren. Unsere Lösung im Detail bestand darin, 1) Module einzuschließen, die nicht über „npm install“ in .gitignore ausgeführt werden sollen, 2) diese Module in packages.json in den Abschnitt „devDependencies“ zu verschieben, 3) npm install ohne das Flag „–production“ auszuführen auf dem Deployment-Rechner, 4) Deployment auf EB

    – h-kippo

    29. September 15 um 10:25 Uhr

.

628420cookie-checkVermeiden Sie den Neuaufbau von node_modules in Elastic Beanstalk

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy