Abhängigkeiten
Was ist ein Lockfile?
Ein Lockfile hält die exakte Version jeder Abhängigkeit fest, die ein Paketmanager aufgelöst hat, direkt und transitiv, damit die nächste Installation denselben Baum erhält. Es ist der beste Plan, den Sie für einen Build haben. Es ist keine Aufzeichnung dessen, was der Build tatsächlich verwendet hat.
Aktualisiert am
Was ein Lockfile festhält
Ihr Manifest, etwa package.json oder pyproject.toml, listet die Pakete auf, von denen Sie abhängen,
und die Versionsbereiche, die Sie akzeptieren. Der Paketmanager macht aus diesen Bereichen exakte Versionen für den gesamten Baum,
einschließlich transitiver Abhängigkeiten, und schreibt das Ergebnis in das Lockfile.
Laut der npm-Dokumentation beschreibt package-lock.json „the exact tree that was generated,
such that subsequent installs are able to generate identical trees“.
Ein einzelner Eintrag in package-lock.json sieht so aus:
"node_modules/raw-body": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz",
"integrity": "sha512-...",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.6.3",
"unpipe": "1.0.0"
}
}
- version ist die exakte gewählte Version.
- resolved gibt an, woher sie geladen wurde: eine Tarball-URL aus der Registry oder eine Git-URL mit einem Commit.
- integrity ist ein Subresource-Integrity-Hash des Tarballs, sodass ein manipulierter Download fehlschlägt.
- dependencies sind seine eigenen Abhängigkeiten, und so wird der Baum oder Abhängigkeitsgraph zusammengefügt.
Lockfiles nach Paketmanager
| Paketmanager | Lockfile | Installation ohne Änderung daran |
|---|---|---|
| npm | package-lock.json | npm ci |
| Yarn (Berry) | yarn.lock | yarn install --immutable |
| pnpm | pnpm-lock.yaml | pnpm install --frozen-lockfile |
| uv | uv.lock | uv sync --locked |
| Poetry | poetry.lock | poetry install |
| Cargo | Cargo.lock | cargo build --locked |
| Bundler | Gemfile.lock | bundle config set frozen true |
| Go-Module | go.mod-Versionen und go.sum-Prüfsummen |
Build-Befehle aktualisieren go.mod standardmäßig nicht |
Bei reinem pip ist der übliche Ersatz eine requirements.txt mit exakten Versionen. Sie pinnt, was sie auflistet,
aber alles, was sie auslässt, wird bei jeder Installation neu aufgelöst.
Nutzen Sie im CI Frozen Installs
Ein Lockfile hilft nur, wenn der Build daraus installiert. Ein einfaches npm install kann
package-lock.json aktualisieren, wenn es nicht mehr zu package.json passt, sodass der Build stillschweigend einen
neuen Baum auflöst. npm ci ist für automatisierte Umgebungen ausgelegt:
- Es verlangt eine
package-lock.jsonodernpm-shrinkwrap.json. - Stimmen Lockfile und
package.jsonnicht überein, bricht es mit einem Fehler ab, statt das Lockfile zu aktualisieren. - Es entfernt zuerst ein vorhandenes
node_modules. - Es schreibt nie in
package.jsonoder das Lockfile.
Die anderen Befehle in der Tabelle oben erledigen dieselbe Aufgabe für ihre Paketmanager.
Anwendungen und Bibliotheken
Committen Sie das Lockfile für Anwendungen und alles, was Sie deployen. Bei Bibliotheken fixiert es nur Ihre eigene Entwicklung
und Ihr CI: npm veröffentlicht package-lock.json nie und ignoriert es überall außer im Root-Projekt. Die
Anwendungen, die Ihre Bibliothek installieren, lösen deren Abhängigkeiten selbst auf, innerhalb Ihrer Versionsbereiche. Die einzige
Ausnahme bei npm ist npm-shrinkwrap.json, das veröffentlicht wird und Vorrang hat und das die meisten
Bibliotheken nicht verwenden sollten.
Warum ein Lockfile keine Aufzeichnung des Ausgelieferten ist
Ein Lockfile ist der Plan für einen Paketmanager in einem Projekt. Der Build, der Ihr Release erzeugt hat, hat mehr getan, als diesem Plan zu folgen:
- Er hat es vielleicht gar nicht genutzt. Eine Installation ohne Frozen-Modus, ein fehlendes Lockfile oder ein zweites Lockfile in einem Monorepo bedeutet, dass der Baum anders aufgelöst wurde als in der Datei, die Sie gerade ansehen.
- Caches. Aus einem CI-Cache wiederhergestellte Pakete werden installiert, ohne geladen zu werden, und ein Cache, der über einen Teilschlüssel wiederhergestellt wurde, kann älter sein als das aktuelle Lockfile. Siehe was der GitHub-Actions-Cache verbirgt.
- Build-Tools. Setup-Actions, Compiler, Linter und Codegeneratoren kommen über andere Kanäle, mit eigenen Abhängigkeitsbäumen.
-
Downloads und Install-Skripte. Ein
curlin einem Build-Schritt oder das Install-Skript eines Pakets lädt Code, den kein Lockfile auflistet. - Basis-Images. Ein Container-Build zieht Images und Betriebssystempakete, die außerhalb jedes sprachspezifischen Lockfiles liegen.
Die Integritäts-Hashes helfen bei all dem nicht. Sie belegen, dass die Pakete im Lockfile nicht manipuliert wurden; sie sagen nichts darüber, was der Build außerhalb davon geladen hat. SCA-Tools, die aus einem Lockfile eine SBOM machen, erben dieselben blinden Flecken.
Den Build aufzeichnen, das Lockfile behalten
Committen Sie Lockfiles weiterhin und installieren Sie mit Frozen Installs daraus. Sie machen Builds wiederholbar. Für die Aufzeichnung dessen, was ein Release enthält, zeichnet CRACI den Build selbst auf: Ein paketbewusster Proxy auf seinen GitHub-Actions-Runnern zeichnet jedes Paket auf, das ein Job lädt, einschließlich der aus CI-Caches wiederhergestellten Pakete, und die SBOM jedes Jobs gibt ihre eigene Vollständigkeit an. Diese Aufzeichnung bietet ein vollständigeres Bild der genutzten Abhängigkeiten als ein Scan des Lockfiles. Siehe SBOMs zur Build-Zeit, oder buchen Sie eine Demo, um beides an einem Ihrer eigenen Builds zu vergleichen.
Lockfiles: häufig gestellte Fragen
Was ist ein Lockfile?
Ein Lockfile ist eine Datei, die ein Paketmanager schreibt, um die exakte Version jeder aufgelösten Abhängigkeit festzuhalten, direkt und transitiv, zusammen mit ihrer Herkunft und einer Prüfsumme. Spätere Installationen lesen sie, um denselben Baum zu reproduzieren, statt Versionsbereiche erneut aufzulösen.
Sollte ich mein Lockfile committen?
Ja, für Anwendungen und alles, was Sie deployen. Ohne committetes Lockfile löst jede frische Installation die Versionsbereiche erneut auf und kann neue transitive Versionen übernehmen. Committen Sie es und installieren Sie im CI mit einem Frozen Install wie npm ci daraus.
Pinnt ein Lockfile transitive Abhängigkeiten?
Ja. Das ist seine Hauptaufgabe. Das Manifest listet nur Ihre direkten Abhängigkeiten und deren erlaubte Bereiche auf; das Lockfile hält die exakte gewählte Version für jedes Paket im Baum fest.
Gelten Lockfiles für Bibliotheken, die ich veröffentliche?
Nicht für Ihre Nutzer. npm zum Beispiel veröffentlicht package-lock.json nie und ignoriert es überall außer im Root-Projekt. Die Anwendungen, die Ihre Bibliothek installieren, lösen deren Abhängigkeiten selbst auf, innerhalb der Bereiche, die Ihre package.json erlaubt.
Was macht das Feld integrity in package-lock.json?
Es enthält einen Subresource-Integrity-Hash des Paket-Tarballs, meist sha512. npm prüft das heruntergeladene Paket dagegen, sodass die Installation eines manipulierten Tarballs für eine im Lockfile festgehaltene Version fehlschlägt. Es schützt die Pakete im Lockfile, nicht das, was der Build außerhalb davon lädt.
Ist ein Lockfile dasselbe wie eine SBOM?
Nein. Ein Lockfile ist eine Eingabe: der Plan, dem ein Paketmanager für ein Projekt folgt. Eine SBOM ist ein Inventar eines Releases. SCA-Tools machen aus einem Lockfile oft eine SBOM, und das funktioniert, wenn der Build genau das Lockfile installiert hat und sonst nichts.
Vergleichen Sie Ihr Lockfile mit Ihrem Build
Lassen Sie einen Workflow auf CRACI laufen und legen Sie die aufgezeichnete SBOM der geladenen Pakete neben das, was Ihr Lockfile angibt.
Demo buchen