Wie kann ich bei Verwendung des Entwicklungs- / Produktionsschalters von Composer die Bereitstellung korrekt durchführen?

178

Composer hat die Möglichkeit, mehrere Abhängigkeiten nur während der Entwicklung zu laden, sodass die Tools nicht in der Produktion (auf dem Live-Server) installiert werden. Dies ist (theoretisch) sehr praktisch für Skripte, die nur in der Entwicklung sinnvoll sind, wie Tests, Tools für gefälschte Daten, Debugger usw.

Der Weg zu gehen ist, einen zusätzlichen require-devBlock mit den Tools hinzuzufügen, die Sie in dev benötigen:

"require-dev": {
    "codeception/codeception": "1.6.0.3"
}

und dann (theoretisch) diese Abhängigkeiten über laden

composer install --dev

Problem & Frage:

Composer hat das Verhalten von installund updateim Jahr 2013 dramatisch geändert. require-devAbhängigkeiten werden jetzt standardmäßig (!) Installiert. Sie können auch eine composer.json mit einem require-devBlock erstellen und eine composer installReproduktion durchführen.

Die am meisten akzeptierte Art der Bereitstellung besteht darin, den Komponisten zu pushen. Sperren Sie (das Ihr aktuelles Composer-Setup enthält) und führen Sie dann eine composer installauf dem Produktionsserver aus. Dadurch wird auch das Entwicklungsmaterial installiert.

Was ist der richtige Weg, um dies bereitzustellen, ohne die -dev-Abhängigkeiten zu installieren?

Hinweis: Ich versuche hier ein kanonisches Q / A zu erstellen, um die seltsame Composer-Bereitstellung zu verdeutlichen. Fühlen Sie sich frei, diese Frage zu bearbeiten.

Sliq
quelle
@all: Weiß nicht, wo das Kopfgeld ist :( Ich werde einen anderen Ansatz beginnen.
Sliq
1
Wenn Sie es nicht aktiv vergeben und keine Antwort akzeptiert wird oder genügend positive Stimmen erhält, erhält niemand das Kopfgeld.
Sven
2
Ich persönlich mag diesen Ansatz überhaupt nicht. Das composer.locksollte NIEMALS zum Git-Repo hinzugefügt werden. Der richtige Ansatz besteht darin, beim Staging das Composer-Update zu verwenden und die Datei dann mit der Produktion zu synchronisieren (wenn natürlich alles funktioniert). Staging muss die exakte Kopie einer Produktionsumgebung sein. composer.locksollte ein Teil von sein .gitignore.
Nomen
6
composer.lock muss definitiv in Ihrer CSV enthalten sein !!! Wie können Sie sonst sicherstellen, dass alle dieselbe Version verwenden? Schließen Sie Composer.lock NIEMALS von Ihrer CSV aus !!!
Tobias Gaertner
3
@TobiasGaertner Ich denke, Sie meinen VCS (Versionskontrollsoftware), aber ansonsten sind Sie korrekt und entsprechen den offiziellen Empfehlungen des Projekts .
Xiong Chiamiov

Antworten:

325

Warum

Es gibt meiner Meinung nach einen guten Grund, warum Composer das --devFlag standardmäßig verwendet (bei Installation und heutzutage Aktualisierung). Composer wird meistens in Szenarien ausgeführt, in denen dies gewünscht ist:

Der grundlegende Workflow für Composer lautet wie folgt:

  • Ein neues Projekt wird gestartet : composer.phar install --dev, json- und lock-Dateien werden an VCS festgeschrieben.
  • Andere Entwickler beginnen mit der Arbeit an dem Projekt: Auschecken von VCS und composer.phar install --dev.
  • Ein Entwickler fügt Abhängigkeiten hinzu: Fügen Sie hinzu composer.phar require <package>, --devwenn Sie das Paket im require-devAbschnitt (und Festschreiben) möchten .
  • Andere gehen mit: (Kasse und) composer.phar install --dev .
  • Ein Entwickler möchte neuere Versionen von Abhängigkeiten: composer.phar update --dev <package> (und Commit).
  • Andere gehen mit: (Kasse und) composer.phar install --dev .
  • Projekt wird bereitgestellt: composer.phar install --no-dev

Wie Sie sehen können, wird die --devFlagge (weit) mehr als die verwendet--no-dev Flag verwendet, insbesondere wenn die Anzahl der Entwickler, die an dem Projekt arbeiten, zunimmt.

Produktionsbereitstellung

Was ist der richtige Weg, um dies bereitzustellen, ohne die "dev" -Abhängigkeiten zu installieren?

Nun, die composer.jsonund composer.lock-Datei sollte an VCS übergeben werden. Nicht auslassen, composer.lockda es wichtige Informationen zu Paketversionen enthält, die verwendet werden sollten.

Wenn Sie eine Produktionsbereitstellung durchführen, können Sie das --no-devFlag an Composer übergeben:

composer.phar install --no-dev

Die composer.lockDatei enthält möglicherweise Informationen zu Entwicklungspaketen. Das ist egal. Das --no-devFlag stellt sicher, dass diese Entwicklungspakete nicht installiert sind.

Wenn ich "Produktionsbereitstellung" sage, meine ich eine Bereitstellung, die auf die Verwendung in der Produktion abzielt. Ich streite nicht darüber, ob a composer.phar installauf einem Produktionsserver oder auf einem Staging-Server durchgeführt werden soll, auf dem Dinge überprüft werden können. Das ist nicht der Umfang dieser Antwort. Ich weise nur darauf hin, wie es gehtcomposer.phar install ohne "dev" -Abhängigkeiten zu installieren.

Offtopic

Das --optimize-autoloaderFlag kann auch in der Produktion wünschenswert sein (es generiert eine Klassenzuordnung, die das automatische Laden in Ihrer Anwendung beschleunigt):

composer.phar install --no-dev --optimize-autoloader

Oder wenn die automatische Bereitstellung abgeschlossen ist:

composer.phar install --no-ansi --no-dev --no-interaction --no-plugins --no-progress --no-scripts --no-suggest --optimize-autoloader

Wenn Ihre Code - Basis unterstützt, könnten Sie tauschen --optimize-autoloaderfür --classmap-authoritative. Mehr Infos hier

Jasper N. Brouwer
quelle
5
Ich stimme den meisten Aussagen mit einer Ausnahme zu. "composer install --no-dev" sollte nur in einer Staging-Umgebung ausgeführt werden und diese Umgebung sollte als unveränderlich angesehen werden. Ich möchte keine Abhängigkeit direkt auf meinen Produktionsserver herunterladen lassen, ohne Vorschau / Staging durchlaufen zu müssen. Das ist nur ein bisschen Vorsicht.
Skalierbar
3
@Scalable: Obwohl ich Ihnen zustimme (und Sven behandelt dies in seiner Antwort gut), ist dies nicht der Umfang meiner Antwort und nicht das, was ich mit "Produktionsbereitstellung" gemeint habe. Ich habe einen Absatz hinzugefügt, um dies zu verdeutlichen.
Jasper N. Brouwer
5
Eigentlich denke ich, dass der Standard die weniger gefährliche Option sein sollte. Es kann fatal sein, --dev als Standard festzulegen und versehentlich eine Composer-Installation in der Produktion durchzuführen.
Hector Ordonez
3
Guter Punkt in der --optimize-autoloader. Beachten Sie auch: --classmap-authoritative- In der Dokumentation hier getcomposer.org/doc/03-cli.md können Sie Folgendes sehen: "Autoload-Klassen nur aus der Klassenzuordnung. Aktiviert implizit --optimize-autoloader", damit Sie verwenden können, wenn Sie die Klassen kennen there ", was wahrscheinlich in Ihrer Produktumgebung passieren sollte, wenn Sie keine Klassen dynamisch generieren.
Xavi Montero
6
Tolle Antwort, ich würde vorschlagen, optimize-autoloaderdirekt in die composer.json:{"config": { "optimize-autoloader": true } }
Yvan
79

Eigentlich würde ich GEGEN die Installation von Abhängigkeiten auf dem Produktionsserver wärmstens empfehlen.

Ich empfehle, den Code auf einem Bereitstellungscomputer auszuchecken, Abhängigkeiten nach Bedarf zu installieren (dies schließt das NICHT-Installieren von Entwicklungsabhängigkeiten ein, wenn der Code in die Produktion geht) und dann alle Dateien auf den Zielcomputer zu verschieben.

Warum?

  • Beim Shared Hosting können Sie möglicherweise keine Befehlszeile aufrufen
  • Selbst wenn Sie dies getan haben, kann PHP dort in Bezug auf Befehle, Speicher oder Netzwerkzugriff eingeschränkt sein
  • Repository-CLI-Tools (Git, Svn) werden wahrscheinlich nicht installiert. Dies würde fehlschlagen, wenn Ihre Sperrdatei eine Abhängigkeit zum Auschecken eines bestimmten Commits aufgezeichnet hat, anstatt dieses Commit als ZIP herunterzuladen (Sie haben --prefer-source oder Composer verwendet) keine andere Möglichkeit, diese Version zu erhalten)
  • Wenn Ihre Produktionsmaschine eher einem kleinen Testserver ähnelt (denken Sie an eine Amazon EC2-Mikroinstanz), ist wahrscheinlich nicht einmal genügend Speicher installiert, um ausgeführt zu werden composer install
  • Während Composer versucht, keine Probleme zu lösen, wie finden Sie es, mit einer teilweise fehlerhaften Produktionswebsite zu enden, da während der Installationsphase von Composers keine zufälligen Abhängigkeiten geladen werden konnten?

Lange Rede, kurzer Sinn: Verwenden Sie Composer in einer Umgebung, die Sie steuern können. Ihre Entwicklungsmaschine ist qualifiziert, da Sie bereits über alle für den Betrieb von Composer erforderlichen Funktionen verfügen.

Was ist der richtige Weg, um dies bereitzustellen, ohne die -dev-Abhängigkeiten zu installieren?

Der zu verwendende Befehl lautet

composer install --no-dev

Dies funktioniert in jeder Umgebung, sei es auf dem Produktionsserver selbst oder auf einer Bereitstellungsmaschine oder auf der Entwicklungsmaschine, die eine letzte Überprüfung durchführen soll, um festzustellen, ob eine Entwicklungsanforderung für die reale Software falsch verwendet wird.

Der Befehl installiert oder deinstalliert die in der Datei composer.lock deklarierten Entwicklungsanforderungen nicht.

Wenn es Ihnen nichts ausmacht, Entwicklungssoftwarekomponenten auf einem Produktionsserver bereitzustellen, composer installwürde das Ausführen denselben Job ausführen, aber einfach die Anzahl der verschobenen Bytes erhöhen und auch eine größere Autoloader-Deklaration erstellen.

Sven
quelle
14
Interessanter Workflow, aber es gibt einen großen Nachteil : Repositorys sollten niemals den Herstellerordner / -inhalt selbst enthalten (offizielle Anweisungen auf der Composer-Seite), damit sie in einer git-basierten Bereitstellung (die ein gängiger Standard ist) niemals direkt in die Produktion übertragen werden. korrigiere mich, wenn ich falsch liege). Die obige Lösung funktioniert also im Grunde nur mit der "alten" FTP-Bereitstellung !? Bitte lassen Sie uns dies weiter diskutieren ...
Sliq
17
Mein vorgeschlagener Workflow beinhaltet nicht das Übertragen des Codes über GIT auf den Produktionsserver. In der Tat würde ich dagegen empfehlen, da Sie dadurch gezwungen werden, Composer-Abhängigkeiten auf dem Produktionsserver zu installieren, was zu einer beliebigen Anzahl von Problemen führen kann. Wenn Ihre Bereitstellung reibungslos ausgeführt werden soll, müssen Sie den gesamten Code zusammenstellen, der zum Ausführen der Anwendung erforderlich ist, bevor Sie die aktuelle Version zerstören und ersetzen. Mögen Sie FTP nicht? RSync über SSH, dann wechseln Sie die Version durch Umdrehen eines Symlinks. Sie können aber auch Push, Checkout und Composer in Prod installieren, wenn Sie möchten.
Sven
2
@Panique: Ich habe gerade diesen Teil Ihres Kommentars gesehen und muss antworten: "In einer Git-basierten Bereitstellung in die Produktion gebracht (was ein gängiger Standard ist, korrigieren Sie mich, wenn ich falsch liege)" - Nein, das hier ist kein allgemeiner Standard. Es ist nur eine Möglichkeit, dies zu tun.
Sven
1
Das Team, dem ich angehöre, hat dies mit großem Erfolg in seinen Workflow aufgenommen. Wir haben eine Build-Maschine (natürlich Jenkins), die: 1) aus SC auscheckt 2) Composer-Installation / Update ausführt 3) Unit-Tests ausführt 4) Dev-Abhängigkeiten entfernt 5) eine Phar-Datei generiert ( app-1.34.pharusw.). Es gibt einen separaten Mechanismus, der benachrichtigt wird und entscheidet, wann diese Datei abgerufen werden soll, wohin sie übertragen werden soll und was dann damit geschehen soll. Einige Teams entscheiden sich dafür, das Phar zu entpacken, sobald es auf dem Server ist, und einige Teams führen es so aus, wie es ist. Dies hat der Stabilität und Reproduzierbarkeit unserer Bereitstellungen viel Vertrauen verliehen.
Josh Johnson
3
Ich stimme dieser Antwort zu 100% zu. Composer sollte weder auf dem Bereitstellungsserver noch auf Git installiert werden. Continuous Deployment / Intergration-Server sollen genau das Abrufen der Quelle und der Abhängigkeiten verwalten: Git Pull> Composer-Installation>
Deployment
4

Jetzt require-devist standardmäßig aktiviert, für die lokale Entwicklung können Sie composer installund composer updateohne die --devOption tun .

Wenn Sie für die Produktion bereitstellen möchten, müssen Sie sicherstellen composer.lock, dass keine Pakete vorhanden sind, von denen sie stammen require-dev.

Sie können dies mit tun

composer update --no-dev

Sobald Sie lokal mit getestet haben --no-dev, können Sie alles für die Produktion bereitstellen und basierend auf dem installieren composer.lock. Sie benötigen die --no-devOption hier erneut, andernfalls sagt der Komponist "Die Sperrdatei enthält keine erforderlichen Entwicklungsinformationen" .

composer install --no-dev

Hinweis: Seien Sie vorsichtig mit allem, was zu Unterschieden zwischen Entwickler und Produktion führen kann! Ich versuche generell, require-dev zu vermeiden, wo immer dies möglich ist, da das Einbeziehen von dev-Tools kein großer Aufwand ist.

dave1010
quelle
1
Dies ist tatsächlich im Detail falsch. Es ist nicht erforderlich, nach Entwicklungsabhängigkeiten composer.lockzu suchen. Du würdest einfach rennencomposer install --no-dev und es werden nur die regulären Abhängigkeiten installiert. Tatsächlich entfernt Composer in diesem Schritt auch alle Entwicklungsabhängigkeiten.
Sven
Wenn mein Lokal composer.lockEntwicklungsabhängigkeiten enthält (und möglicherweise die Versionen von Nicht-Entwicklungspaketen beeinflusst), möchte ich es aktualisieren, um zu reflektieren, wie es in der Produktion sein würde. Dies zwingt Sie auch dazu, composer install --no-devin der Produktion zu laufen , ebenso composer installwie Fehler. Technisch denke ich, dass Sie Recht haben; Dies ist nicht erforderlich, aber es ist ein zusätzliches Maß an Sicherheit, das mir gefällt.
Dave1010
Ok, Demo-Szenario: Ihre App benötigt dev/toolund prod/lib:~1.0. Das neueste Produkt / lib ist 1.3, aber dev / tool benötigt auch prod/lib:1.1.*. Ergebnis: Sie installieren Version 1.1.9 (neueste Version von 1.1.x) und verwenden sie während Ihrer Entwicklung. Ich würde sagen, es ist NICHT sicher, nur zu aktualisieren --no-dev, also das neueste Produkt / lib 1.3 einzuschließen und davon auszugehen, dass alles ohne Tests funktioniert. Und vielleicht ist das Testen dann unmöglich, weil es an Entwicklern / Werkzeugen mangelt. Ich würde annehmen, dass dev / tool, da es in der Produktion nicht benötigt wird, nicht ausgerollt werden sollte, aber die Software dann prod / lib 1.1.9 verwenden muss.
Sven
Wenn Sie verwenden --no-dev, müssen Sie es lokal testen, wie in der Antwort erwähnt. Ich würde trotzdem empfehlen, überhaupt nicht zu verwenden --no-dev.
Dave1010
Im Grunde schlagen Sie Folgendes vor: Führen Sie composer updatedann eine Entwicklung durch, führen Sie composer update --no-devdann die Release-Tests durch, gehen Sie dann zur Produktion und tun Sie dies composer install --no-dev. Zwei Probleme: 1. Ich kann die Version nicht ohne Entwicklungsabhängigkeiten testen und 2. Ich kann zum Beispiel nicht mit Git in der Produktion installieren.
Sven
3

Auf Produktionsservern benenne ich vendorauf vendor-<datetime>, und während des Einsatzes werden zwei Anbieter dirs haben.

Ein HTTP-Cookie veranlasst mein System, den neuen Anbieter auszuwählen autoload.php , und nach dem Testen schalte ich vollständig atomar / sofort zwischen ihnen um, um das alte Anbieterverzeichnis für alle zukünftigen Anforderungen zu deaktivieren. Einige Tage später lösche ich das vorherige Verzeichnis.

Dies vermeidet Probleme, die durch Dateisystem-Caches verursacht werden, die ich in Apache / PHP verwende, und ermöglicht es auch, dass aktiver PHP-Code weiterhin das vorherige Herstellerverzeichnis verwendet.


Trotz anderer Empfehlungen, die dagegen sprechen, laufe ich persönlich composer installauf dem Server, da dies in meinem Staging-Bereich (einer VM auf meinem Laptop) schneller ist als rsync.

Ich benutze --no-dev --no-scripts --optimize-autoloader. Sie sollten die Dokumente für jedes Dokument lesen, um zu überprüfen, ob dies für Ihre Umgebung geeignet ist.

Abhi Beckert
quelle
2

Ich denke, es ist besser, den Prozess zu automatisieren:

Fügen Sie die Datei composer.lock in Ihr Git-Repository ein und stellen Sie sicher, dass Sie composer.phar install --no-dev verwenden beim Freigeben , aber Dev-Computer können Sie jeden Composer-Befehl ohne Bedenken verwenden. Dies geht nicht in die Produktion Die Produktion basiert ihre Abhängigkeiten in der Sperrdatei.

Auf dem Server checken Sie diese bestimmte Version oder Bezeichnung aus und führen alle Tests aus, bevor Sie die App ersetzen. Wenn die Tests erfolgreich sind, setzen Sie die Bereitstellung fort.

Wenn der Test von Entwicklungsabhängigkeiten abhängt, da Composer keine Testbereichsabhängigkeit hat, könnte eine nicht sehr elegante Lösung den Test mit den Entwicklungsabhängigkeiten ausführen ( composer.phar install ) auszuführen, die Herstellerbibliothek zu entfernen und composer.phar install auszuführen. -no-dev erneut, dies verwendet zwischengespeicherte Abhängigkeiten, ist also schneller. Dies ist jedoch ein Hack, wenn Sie das Konzept der Bereiche in anderen Build-Tools kennen

Automatisiere das und vergiss den Rest, trink ein Bier :-)

PS.: Wie im folgenden Kommentar zu @Sven ist es keine gute Idee, die Datei composer.lock nicht auszuchecken, da dadurch die Composer-Installation als Composer-Update funktioniert.

Sie können diese Automatisierung mit http://deployer.org/ durchführen. Es ist ein einfaches Tool.

Giovanni Silva
quelle
2
Wenn Sie sich nicht festlegen und nicht auschecken, composer.lockwird sich das so composer installverhalten composer update. Die von Ihnen bereitgestellten Versionen sind also nicht die, mit denen Sie entwickelt haben. Dies kann zu Problemen führen (und dies vor allem angesichts des erst kürzlich gelösten Sicherheitsproblems mit "Ersetzen" in Composer). Sie sollten NIEMALS composer updateunbeaufsichtigt laufen, ohne zu überprüfen, ob nichts kaputt gegangen ist.
Sven
1
@Sven Dies ist ein Vorschlag im selben Kommentar, Unit-Tests vor der Bereitstellung automatisch auszuführen. Aber Sie haben Recht, es ist besser, die Datei composer.lock trotzdem aufzubewahren.
Giovanni Silva
Jetzt müssen Sie nur noch erklären: Wie führen Sie die Tests auf dem Server ohne die Dev-Abhängigkeiten wie PHPUnit aus?
Sven
Wäre sehr schön, wenn Abhängigkeiten, Tests und Bereitstellung in einem Tool wie Java Gradle oder SBT oder sogar Maven zusammengefasst wären (Maven ist nicht so gut). Ein PHP-Tool, mit dem Composer PHPUNIT und Deployment zusammenarbeiten. Oder sogar ein Gradle- oder Scala-SBT-Plugin, um dies zu erreichen. Da es sich um agnostische Build-Tools handelt, kann das Plugin sogar mit Ressourcen wie der Minimierung von Javascript und dem Kompilieren von Sass sowie der Minimierung von CSS arbeiten. Weiß jemand etwas?
Giovanni Silva
1
Natürlich wird dies auf dem Server durchgeführt, um die reale Umgebung zu testen, aber nicht direkt auf der Site vhost. Sie können dies in einem separaten temporären Ordner tun und das Ergebnis nach Erfolg auf den vhost verschieben
Giovanni Silva