Comment déployer correctement lors de l'utilisation du commutateur de développement / production de Compositeur?

180

Composer a la possibilité de charger plusieurs dépendances uniquement pendant le développement, de sorte que les outils ne seront pas installés en production (sur le serveur live). C'est (en théorie) très pratique pour les scripts qui n'ont de sens qu'en développement, comme les tests, les faux outils de données, le débogueur, etc.

La solution consiste à ajouter un require-devbloc supplémentaire avec les outils dont vous avez besoin en dev:

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

puis (théoriquement) charger ces dépendances via

composer install --dev

Problème et question:

Composer a radicalement changé le comportement de installet updateen 2013, les require-devdépendances sont désormais installées par défaut (!), N'hésitez pas à créer un composer.json avec un require-devbloc et à effectuer une composer installreproduction.

Car le moyen le plus accepté de déployer est de pousser le compositeur. lock (qui contient votre configuration actuelle du compositeur), puis effectuez uncomposer install sur le serveur de production, cela installera également les éléments de développement.

Quelle est la bonne façon de déployer ceci sans installer les dépendances -dev?

Remarque: j'essaie de créer un Q / R canonique ici pour clarifier le déploiement étrange de Composer. N'hésitez pas à modifier cette question.

Sliq
la source
@all: Je ne sais pas où est la prime: (Je vais commencer une autre approche.
Sliq
1
Si vous ne l'attribuez pas activement et qu'aucune réponse n'est acceptée ou ne reçoit suffisamment de votes positifs, personne n'obtient la prime.
Sven
2
Personnellement, je n'aime pas du tout cette approche. Le composer.lockne doit jamais être ajouté au repo Git, JAMAIS. La bonne approche consiste à utiliser la mise à jour du compositeur sur la mise en scène, puis à synchroniser le fichier en production (si tout fonctionne, bien sûr). La préparation doit être la copie exacte d'un environnement de production. composer.lockdevrait faire partie de .gitignore.
substantif
6
composer.lock doit définitivement être inclus dans votre CSV !!! Sinon, comment vous assurez-vous que tout le monde utilise la même version? Alors NE JAMAIS exclure composer.lock de votre CSV !!!
Tobias Gaertner
3
@TobiasGaertner Je pense que vous voulez dire VCS (logiciel de contrôle de version), mais sinon, vous avez raison et en ligne avec les recommandations officielles du projet .
Xiong Chiamiov

Réponses:

327

Pourquoi

Il y a à mon humble avis une bonne raison pour laquelle Composer utilisera le --devdrapeau par défaut (lors de l'installation et mise à jour) de nos jours. Composer est principalement exécuté dans les scénarios où c'est le comportement souhaité:

Le flux de travail de base de Composer est le suivant:

  • Un nouveau projet est démarré: les composer.phar install --devfichiers json et lock sont validés dans VCS.
  • D'autres développeurs commencent à travailler sur le projet: extraction de VCS et composer.phar install --dev.
  • Un développeur ajoute des dépendances:, composer.phar require <package>ajoutez --devsi vous voulez le package dans la require-devsection (et validez).
  • D'autres vont le long: (checkout et) composer.phar install --dev .
  • Un développeur souhaite des versions plus récentes des dépendances: composer.phar update --dev <package> (et commit).
  • D'autres vont le long: (checkout et) composer.phar install --dev .
  • Le projet est déployé: composer.phar install --no-dev

Comme vous pouvez le voir, le --devdrapeau est (beaucoup) plus utilisé que le --no-devdrapeau, surtout lorsque le nombre de développeurs travaillant sur le projet augmente.

Déploiement de production

Quelle est la bonne façon de déployer cela sans installer les dépendances "dev"?

Eh bien, le fichier composer.jsonet composer.lockdoit être validé dans VCS. Ne l'omettez pas composer.lockcar il contient des informations importantes sur les versions de package à utiliser.

Lors de l'exécution d'un déploiement de production, vous pouvez transmettre l' --no-devindicateur à Composer:

composer.phar install --no-dev

Le composer.lockfichier peut contenir des informations sur les packages de développement. Cela n'a pas d'importance. L' --no-devindicateur s'assurera que ces paquets de développement ne sont pas installés.

Quand je dis «déploiement de production», je veux dire un déploiement qui vise à être utilisé en production. Je ne dis pas si uncomposer.phar install devrait être fait sur un serveur de production, ou sur un serveur intermédiaire où les choses peuvent être examinées. Ce n'est pas la portée de cette réponse. Je montre simplement comment faire composer.phar installsans installer les dépendances "dev".

Hors sujet

Le --optimize-autoloaderdrapeau peut également être souhaitable en production (il génère un class-map qui accélérera le chargement automatique dans votre application):

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

Ou lorsque le déploiement automatisé est effectué:

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

Si votre base de code le prend en charge, vous pouvez le remplacer --optimize-autoloaderpar --classmap-authoritative. Plus d'infos ici

Jasper N. Brouwer
la source
5
Je suis d'accord avec la plupart de ce qui est dit à une exception près. "composer install --no-dev" ne doit être exécuté que dans un environnement intermédiaire et cet environnement doit être considéré comme immuable. Je ne voudrais pas avoir une dépendance téléchargée directement sur mon serveur de production et sans passer par l'aperçu / la mise en scène. C'est juste un peu plus de prudence.
Évolutif du
3
@Scalable: Bien que je sois d'accord avec vous (et Sven le couvre bien dans sa réponse), ce n'est pas la portée de ma réponse, et pas ce que je voulais dire par "déploiement de production". J'ai ajouté un paragraphe pour clarifier cela.
Jasper N.Brouwer
5
En fait, je pense que la valeur par défaut devrait être l'option la moins dangereuse. Faire de --dev la valeur par défaut et faire accidentellement une installation de compositeur en production pourrait être fatal.
Hector Ordonez
3
Bon point dans le --optimize-autoloader. Considérez aussi --classmap-authoritative- De la documentation ici getcomposer.org/doc/03-cli.md, vous pouvez voir ceci: "Chargement automatique des classes à partir du classmap uniquement. Active implicitement --optimize-autoloader" afin que vous puissiez utiliser si vous connaissez les classes "sont there ", ce qui devrait probablement se produire dans votre environnement prod, sauf si vous générez des classes dynamiquement.
Xavi Montero
6
Excellente réponse, je suggérerais d'ajouter optimize-autoloaderdirectement dans le composer.json:{"config": { "optimize-autoloader": true } }
Yvan
79

En fait, je recommanderais fortement CONTRE d'installer les dépendances sur le serveur de production.

Ma recommandation est de récupérer le code sur une machine de déploiement, d'installer les dépendances si nécessaire (cela inclut de NE PAS installer de dépendances de développement si le code passe en production), puis de déplacer tous les fichiers vers la machine cible.

Pourquoi?

  • sur l'hébergement partagé, vous ne pourrez peut-être pas accéder à une ligne de commande
  • même si vous le faisiez, PHP pourrait y être limité en termes de commandes, de mémoire ou d'accès au réseau
  • Les outils CLI du référentiel (Git, Svn) ne seront probablement pas installés, ce qui échouerait si votre fichier de verrouillage a enregistré une dépendance pour extraire un certain commit au lieu de télécharger ce commit au format ZIP (vous avez utilisé --prefer-source, ou Composer avait pas d'autre moyen d'obtenir cette version)
  • si votre machine de production ressemble plus à un petit serveur de test (pensez à la micro-instance Amazon EC2), il n'y a probablement même pas assez de mémoire installée pour s'exécuter composer install
  • tandis que le compositeur essaie de ne pas casser les choses, que pensez-vous de la fin avec un site Web de production partiellement cassé parce qu'une dépendance aléatoire n'a pas pu être chargée pendant la phase d'installation des compositeurs

En bref: utilisez Composer dans un environnement que vous pouvez contrôler. Votre machine de développement est éligible car vous disposez déjà de tout ce dont vous avez besoin pour faire fonctionner Composer.

Quelle est la bonne façon de déployer ceci sans installer les dépendances -dev?

La commande à utiliser est

composer install --no-dev

Cela fonctionnera dans n'importe quel environnement, que ce soit le serveur de production lui-même, une machine de déploiement ou la machine de développement qui est censée effectuer une dernière vérification pour déterminer si une exigence de développement est incorrectement utilisée pour le logiciel réel.

La commande n'installe ni ne désinstalle activement les exigences de développement déclarées dans le fichier composer.lock.

Si cela ne vous dérange pas de déployer des composants logiciels de développement sur un serveur de production, l'exécution composer installferait le même travail, mais augmenterait simplement la quantité d'octets déplacés et créerait également une déclaration de chargeur automatique plus grande.

Sven
la source
14
Flux de travail intéressant, mais il y a un gros inconvénient : les référentiels ne doivent jamais contenir le dossier / contenu du fournisseur lui-même (déclarations officielles sur la page Composer), donc ils ne seront jamais directement poussés en production dans un déploiement basé sur git (qui est un standard courant, afaik, Corrige moi si je me trompe). Donc, fondamentalement, la solution ci-dessus ne fonctionne qu'avec un déploiement FTP «à l'ancienne»!? Veuillez discuter de cela plus en détail ...
Sliq
17
Mon workflow suggéré n'inclut pas la transmission du code via GIT vers le serveur de production. En fait, je vous le déconseille, car cela vous obligera à installer les dépendances de Composer sur le serveur de production, ce qui peut soulever un certain nombre de problèmes. Si vous souhaitez que votre déploiement se déroule sans heurts, vous devez assembler tout le code nécessaire pour exécuter l'application avant de détruire la version actuelle et de la remplacer. Vous n'aimez pas FTP? RSync via SSH, puis changez de version en retournant un lien symbolique. Mais vous pouvez également pousser, vérifier et installer le compositeur dans prod si vous le souhaitez.
Sven
2
@Panique: Je viens de voir cette partie de votre commentaire et je dois répondre: "poussé en production dans un déploiement basé sur git (qui est un afaik standard courant, corrigez-moi si je me trompe)" - Non, ça n'est pas une norme commune. C'est juste une façon de le faire.
Sven
1
L'équipe dont je fais partie a intégré cela dans son flux de travail avec beaucoup de succès. Nous avons une machine de construction (Jenkins, bien sûr) qui: 1) extrait de SC 2) exécute l'installation / mise à jour du compositeur 3) exécute des tests unitaires 4) supprime les dépendances de développement 5) génère un fichier phar ( app-1.34.pharetc.). Il existe un mécanisme distinct qui est notifié et décide quand récupérer ce fichier, où le transférer, puis quoi en faire. Certaines équipes choisissent de décompresser le phar une fois qu'il est sur le serveur et certaines équipes l'exécutent tel quel. Cela a donné beaucoup de confiance à la stabilité et à la reproductibilité de nos déploiements.
Josh Johnson
3
Je suis d'accord à 100% avec cette réponse. Composer ne doit pas être installé sur le serveur de déploiement, ni git. Les serveurs de déploiement / intégration continus sont exactement censés gérer la source et les dépendances en récupérant: git pull> composer install> deploy
Eric MORAND
4

Maintenant require-devest activé par défaut, pour le développement local, vous pouvez faire composer installet composer updatesans le--dev option.

Lorsque vous souhaitez effectuer un déploiement en production, vous devez vous assurer composer.lockqu'aucun package ne provient derequire-dev .

Vous pouvez le faire avec

composer update --no-dev

Une fois que vous avez testé localement avec, --no-devvous pouvez tout déployer en production et installer en fonction du composer.lock. Vous avez à nouveau besoin de l' --no-devoption ici, sinon le compositeur dira "Le fichier de verrouillage ne contient pas d'informations require-dev" .

composer install --no-dev

Remarque: soyez prudent avec tout ce qui a le potentiel d'introduire des différences entre le développement et la production! J'essaie généralement d'éviter require-dev dans la mesure du possible, car inclure des outils de développement n'est pas une grosse surcharge.

dave1010
la source
1
C'est en fait incorrect dans les détails. Il n'est pas nécessaire de vérifier les composer.lockdépendances de développement. Vous exécuteriez simplement composer install --no-dev, et vous n'obtiendrez que les dépendances régulières installées - en fait, Composer supprimera également toutes les dépendances de développement à cette étape.
Sven
Si mon local composer.lockcontenait des dépendances de développement (et affectait potentiellement les versions de packages non-dev), je voudrais le mettre à jour pour refléter comment il serait en production. Cela vous oblige également à exécuter composer install --no-deven production, tout comme composer installl'erreur. Techniquement, je pense que vous avez raison; ce n'est pas obligatoire, mais c'est un niveau de sécurité supplémentaire, ce que j'aime.
dave1010
Ok, scénario de démonstration: votre application nécessite dev/toolet prod/lib:~1.0. Le plus récent prod / lib est 1.3, mais dev / tool nécessite également prod/lib:1.1.*. Résultat: vous allez installer la version 1.1.9 (la plus récente de la branche 1.1.x) et l'utiliser pendant votre développement. Je dirais qu'il n'est PAS sûr de simplement mettre à jour --no-dev, incluez donc le plus récent prod / lib 1.3 et supposez que tout fonctionne sans test. Et peut-être que les tests sont alors impossibles à cause du manque de développement / outil. Je suppose que parce que dev / tool n'est pas nécessaire en production, il ne devrait pas être déployé, mais le logiciel doit alors utiliser prod / lib 1.1.9.
Sven
Si vous utilisez, --no-devvous devez le tester localement, comme je l'ai mentionné dans la réponse. Je recommanderais quand même de ne pas utiliser --no-devdu tout.
dave1010
Donc, fondamentalement, vous suggérez ceci:, composer updatepuis faites du développement, puis faites composer update --no-dev, puis faites les tests de version, puis passez à la production et faites composer install --no-dev. Deux problèmes: 1. Je ne peux pas tester la version sans dépendances de développement, et 2. Je ne peux pas installer avec par exemple Git en production.
Sven
3

Sur les serveurs de production je renomme vendoràvendor-<datetime> et pendant le déploiement aura deux dirs fournisseurs.

Un cookie HTTP oblige mon système à choisir le nouveau fournisseur autoload.php , et après les tests, je fais un basculement entièrement atomique / instantané entre eux pour désactiver l'ancien répertoire du fournisseur pour toutes les demandes futures, puis je supprime le répertoire précédent quelques jours plus tard.

Cela évite tout problème causé par les caches du système de fichiers que j'utilise dans apache / php, et permet également à tout code PHP actif de continuer à utiliser le répertoire précédent du fournisseur.


Malgré d'autres réponses qui le déconseillent, je cours personnellement composer install sur le serveur, car c'est plus rapide que rsync depuis ma zone de préparation (une VM sur mon ordinateur portable).

J'utilise --no-dev --no-scripts --optimize-autoloader. Vous devriez lire les documents pour chacun d'eux pour vérifier si cela est approprié à votre environnement.

Abhi Beckert
la source
2

Je pense qu'il vaut mieux automatiser le processus:

Ajoutez le fichier composer.lock dans votre référentiel git, assurez-vous d'utiliser composer.phar install --no-dev lorsque vous relâchez, mais dans votre machine de développement, vous pouvez utiliser n'importe quelle commande composer sans souci, cela n'ira pas en production, le production basera ses dépendances dans le fichier de verrouillage.

Sur le serveur, vous extrayez cette version ou cette étiquette spécifique et exécutez tous les tests avant de remplacer l'application, si les tests réussissent, vous poursuivez le déploiement.

Si le test dépend de dépendances de développement, comme composer n'a pas de dépendance de portée de test, une solution pas très élégante pourrait être d'exécuter le test avec les dépendances de développement ( installer composer.phar ), supprimer la bibliothèque du fournisseur, exécuter installer composer.phar - -no-dev encore une fois, cela utilisera les dépendances mises en cache, donc c'est plus rapide. Mais c'est un hack si vous connaissez le concept de portées dans d'autres outils de construction

Automatisez ça et oubliez le reste, allez boire une bière :-)

PS: Comme dans le commentaire @Sven ci-dessous, ce n'est pas une bonne idée de ne pas extraire le fichier composer.lock, car cela fera fonctionner l'installation du compositeur en tant que mise à jour du compositeur.

Vous pouvez faire cette automatisation avec http://deployer.org/ c'est un outil simple.

Giovanni Silva
la source
2
Ne pas s'engager et vérifier composer.lockfera composer installagir comme composer update. Les versions que vous déployez ne sont donc pas celles avec lesquelles vous avez développé. Ceci est susceptible de générer des problèmes (et plus encore à la lumière du seul problème de sécurité résolu récemment avec «remplacer» dans Composer). Vous ne devriez JAMAIS courir composer updatesans surveillance sans vérifier qu'il n'a rien cassé.
Sven
1
@Sven c'est une manière de suggérer dans le même commentaire d'exécuter des tests unitaires automatiquement avant le déploiement. Mais vous avez raison, il vaut mieux garder le fichier composer.lock quand même.
Giovanni Silva
Maintenant, la seule chose que vous auriez à expliquer: comment exécuter les tests sur le serveur sans les dépendances de développement comme PHPUnit?
Sven
Ce serait très bien si les dépendances, les tests et le déploiement étaient regroupés dans un seul outil, comme Java Gradle ou SBT ou même Maven (maven n'est pas si bon). Un outil PHP qui permet à composer phpunit et le déploiement de fonctionner ensemble. Ou même un plugin Gradle ou Scala SBT pour faire ces choses, car ce sont des outils de construction agnostiques, le plugin pourrait même fonctionner avec des actifs tels que la minimisation du javascript et la compilation de sass, minimisant le CSS. Quelqu'un sait quelque chose?
Giovanni Silva
1
Bien sûr, cela se fait dans le serveur pour tester l'environnement réel, mais pas directement dans le site vhost, vous pouvez le faire dans un dossier temporaire séparé et déplacer le résultat vers le vhost en cas de réussite
Giovanni Silva