Come distribuire correttamente quando si utilizza lo switch di sviluppo / produzione di Composer?


180

Composer ha la possibilità di caricare diverse dipendenze solo durante lo sviluppo, quindi gli strumenti non verranno installati in produzione (sul server live). Questo è (in teoria) molto utile per gli script che hanno senso solo nello sviluppo, come test, strumenti per dati falsi, debugger, ecc.

La strada da percorrere è aggiungere un require-devblocco aggiuntivo con gli strumenti necessari in dev:

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

e quindi (teoricamente) caricare queste dipendenze tramite

composer install --dev

Problema e domanda:

Il compositore ha cambiato radicalmente il comportamento installe, updatenel 2013, le require-devdipendenze sono ora installate per impostazione predefinita (!), Sentiti libero di creare un composer.json con un require-devblocco e di eseguire una composer installriproduzione.

Come il modo più accettato di distribuire è spingere il compositore. lock (che contiene la tua attuale configurazione del compositore) e quindi esegui uncomposer install sul server di produzione, questo installerà anche le cose di sviluppo.

Qual è il modo corretto di distribuire questo senza installare le dipendenze -dev?

Nota: sto cercando di creare un Q / A canonico qui per chiarire la strana distribuzione di Composer. Sentiti libero di modificare questa domanda.


@tutti: non so dove sia la generosità :( inizierò un altro approccio.
Sliq

1
Se non lo assegni attivamente e nessuna risposta viene accettata o ottiene abbastanza voti, nessuno ottiene la generosità.
Sven,

2
Personalmente non mi piace affatto questo approccio. Non composer.lockdovrebbe mai essere aggiunto al repository Git, MAI. L'approccio corretto consiste nell'utilizzare l'aggiornamento del compositore per la gestione temporanea e quindi sincronizzare il file in produzione (se tutto funziona, ovviamente). La gestione temporanea deve essere la copia esatta di un ambiente di produzione. composer.lockdovrebbe far parte di .gitignore.
sostantivo

6
compositore.lock deve essere sicuramente incluso nel tuo CSV !!! In quale altro modo ti assicuri che tutti utilizzino la stessa versione ?? Quindi NON escludere MAI composer.lock dal tuo CSV !!!
Tobias Gaertner,

3
@TobiasGaertner Penso che intendi VCS (software di controllo della versione), ma per il resto sei corretto e in linea con le raccomandazioni ufficiali del progetto .
Xiong Chiamiov

Risposte:


327

Perché

C'è IMHO un buon motivo per cui Composer utilizzerà il --devflag di default (su install e aggiornamento) al giorno d'oggi. Il compositore viene eseguito principalmente negli scenari in cui si desidera questo comportamento:

Il flusso di lavoro di base di Composer è il seguente:

  • Viene avviato un nuovo progetto composer.phar install --dev:, i file json e lock vengono sottoposti a commit in VCS.
  • Altri sviluppatori iniziano a lavorare al progetto: checkout di VCS e composer.phar install --dev.
  • Uno sviluppatore aggiunge dipendenze:, composer.phar require <package>aggiungi --devse vuoi il pacchetto nella require-devsezione (e commetti).
  • Altri vanno avanti: (checkout e) composer.phar install --dev .
  • Uno sviluppatore desidera versioni più recenti di dipendenze: composer.phar update --dev <package> (e commit).
  • Altri vanno avanti: (checkout e) composer.phar install --dev .
  • Il progetto è distribuito: composer.phar install --no-dev

Come puoi vedere, la --devbandiera viene usata (molto) più della --no-devbandiera, specialmente quando aumenta il numero di sviluppatori che lavorano al progetto.

Distribuzione di produzione

Qual è il modo corretto di distribuire questo senza installare le dipendenze "dev"?

Bene, il file composer.jsone composer.lockdovrebbe essere affidato a VCS. Non omettere composer.lockperché contiene informazioni importanti sulle versioni dei pacchetti che dovrebbero essere utilizzate.

Quando si esegue una distribuzione di produzione, è possibile passare il --no-devflag a Composer:

composer.phar install --no-dev

Il composer.lockfile potrebbe contenere informazioni sui pacchetti dev. Questo non importa. Il --no-devflag assicurerà che quei pacchetti dev non siano installati.

Quando dico "distribuzione di produzione", intendo una distribuzione che ha lo scopo di essere utilizzata nella produzione. Non sto discutendo se un composer.phar installdovrebbe essere fatto su un server di produzione o su un server di gestione temporanea in cui le cose possono essere riviste. Questo non è lo scopo di questa risposta. Sto solo sottolineando come composer.phar installinstallare senza dipendenze "dev".

Fuori tema

Il --optimize-autoloaderflag potrebbe anche essere desiderabile durante la produzione (genera una mappa di classi che accelererà il caricamento automatico nella tua applicazione):

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

O quando viene eseguita la distribuzione automatica:

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

Se il codebase lo supporta, si potrebbe scambiare --optimize-autoloaderper --classmap-authoritative. Maggiori informazioni qui


5
Sono d'accordo con la maggior parte di ciò che viene detto con un'eccezione. "compositore install --no-dev" dovrebbe essere eseguito solo in un ambiente di staging e quell'ambiente dovrebbe essere considerato immutabile. Non vorrei scaricare alcuna dipendenza direttamente sul mio server di produzione e senza passare in anteprima / gestione temporanea. Questo è solo un ulteriore avvertimento.
Scalabile

3
@Scalable: Anche se sono d'accordo con te (e Sven lo copre bene nella sua risposta), non è questo lo scopo della mia risposta, e non quello che intendevo con "distribuzione della produzione". Ho aggiunto un paragrafo per chiarirlo.
Jasper N. Brouwer il

5
In realtà penso che l'impostazione predefinita dovrebbe essere l'opzione meno pericolosa. L'impostazione predefinita di --dev e l'installazione accidentale di un compositore in produzione potrebbe essere fatale.
Hector Ordonez,

3
Buon punto nel --optimize-autoloader. Considera anche --classmap-authoritative- Dalla documentazione qui getcomposer.org/doc/03-cli.md puoi vedere questo: "Carica automaticamente le classi solo dalla classmap. Abilita implicitamente --optimize-autoloader" in modo da poter usare se sai che le classi "sono ", che probabilmente dovrebbe accadere nel tuo ambiente di produzione a meno che non generi dinamicamente delle classi.
Xavi Montero,

6
Ottima risposta, suggerirei di aggiungere optimize-autoloaderdirettamente nel composer.json:{"config": { "optimize-autoloader": true } }
Yvan

79

In realtà, consiglio vivamente CONTRO di installare dipendenze sul server di produzione.

La mia raccomandazione è di verificare il codice su una macchina di distribuzione, installare le dipendenze secondo necessità (questo include NON installare dipendenze di sviluppo se il codice va in produzione) e quindi spostare tutti i file sulla macchina di destinazione.

Perché?

  • sull'hosting condiviso, potresti non essere in grado di accedere a una riga di comando
  • anche se lo facessi, PHP potrebbe essere limitato lì in termini di comandi, memoria o accesso alla rete
  • è probabile che gli strumenti della CLI del repository (Git, Svn) non vengano installati, il che fallirebbe se il tuo file di blocco ha registrato una dipendenza per il checkout di un certo commit invece di scaricarlo come ZIP (hai usato --prefer-source, o Composer aveva nessun altro modo per ottenere quella versione)
  • se la tua macchina di produzione è più simile a un piccolo server di prova (pensa ad una microistanza di Amazon EC2) probabilmente non è nemmeno installata memoria sufficiente per eseguire composer install
  • mentre il compositore cerca di non interrompere le cose, come ti senti a finire con un sito Web di produzione parzialmente rotto perché non è stato possibile caricare una dipendenza casuale durante la fase di installazione di Composers

Per farla breve: usa Composer in un ambiente che puoi controllare. La tua macchina di sviluppo si qualifica perché hai già tutto ciò che è necessario per far funzionare Composer.

Qual è il modo corretto di distribuire questo senza installare le dipendenze -dev?

Il comando da usare è

composer install --no-dev

Funzionerà in qualsiasi ambiente, sia esso il server di produzione stesso, o una macchina di distribuzione, o la macchina di sviluppo che dovrebbe fare un ultimo controllo per scoprire se qualsiasi requisito di sviluppo è usato in modo errato per il software reale.

Il comando non installa né disinstalla attivamente i requisiti di sviluppo dichiarati nel file composer.lock.

Se non ti dispiace distribuire componenti software di sviluppo su un server di produzione, l'esecuzione composer installfarebbe lo stesso lavoro, ma aumenterebbe semplicemente la quantità di byte spostati e creerebbe anche una dichiarazione di caricamento automatico più grande.


14
Flusso di lavoro interessante, ma c'è un grande svantaggio : i repository non devono mai contenere la cartella / i contenuti del fornitore stesso (dichiarazioni ufficiali sulla pagina Composer), quindi non verranno mai spinti direttamente alla produzione in una distribuzione basata su git (che è uno standard comune, correggimi se sbaglio). Quindi sostanzialmente la soluzione sopra funziona solo con la distribuzione FTP "vecchia scuola" !? Per favore, discutiamolo ulteriormente ...
Sliq,

17
Il mio flusso di lavoro suggerito non include l'invio del codice tramite GIT al server di produzione. In effetti, lo sconsiglio, perché in tal modo ti costringerai a installare le dipendenze di Composer sul server di produzione, il che può far sorgere un numero qualsiasi di problemi. Se si desidera che la distribuzione venga eseguita senza problemi, è necessario assemblare tutto il codice necessario per eseguire l'applicazione prima di distruggere la versione corrente e sostituirla. Non ti piace FTP? RSync tramite SSH, quindi cambia versione lanciando un collegamento simbolico. Ma puoi anche spingere, fare il checkout e installare il compositore in prod, se vuoi.
Sven,

2
@Panique: ho appena visto quella parte del tuo commento e devo rispondere: "spinto alla produzione in una distribuzione basata su git (che è uno standard comune, correggimi se sbaglio)" - No, questo non è uno standard comune. È solo un modo per farlo.
Ser

1
Il team in cui mi trovo ha incorporato questo nel loro flusso di lavoro con grande successo. Abbiamo una build machine (Jenkins, ovviamente) che: 1) verifica da SC 2) esegue il compositore installa / aggiorna 3) esegue unit test 4) rimuove le dipendenze degli sviluppatori 5) genera un file phar ( app-1.34.pharecc.). C'è un meccanismo separato che viene notificato e decide quando prendere quel file, dove trasferirlo, e poi cosa fare con esso. Alcuni team scelgono di decomprimere il phar una volta che si trova sul server e alcuni team lo eseguono così com'è. Ha prestato molta fiducia alla stabilità e alla riproducibilità dei nostri schieramenti.
Josh Johnson,

3
Sono d'accordo al 100% con questa risposta. Composer non deve essere installato sul server di distribuzione, né git. Si suppone che i server di distribuzione / integrazione continui gestiscano esattamente il recupero della fonte e delle dipendenze: git pull> installazione del compositore> deploy
Eric MORAND,

4

Ora require-devè abilitato per impostazione predefinita, per lo sviluppo locale è possibile fare composer installe composer updatesenza--dev opzione.

Quando si desidera distribuire in produzione, è necessario assicurarsi composer.lockche non siano presenti pacchetti provenientirequire-dev .

Puoi farlo con

composer update --no-dev

Una volta testato localmente --no-dev, puoi distribuire tutto alla produzione e all'installazione in base al composer.lock. Qui hai di nuovo bisogno --no-devdell'opzione, altrimenti il ​​compositore dirà "Il file di blocco non contiene informazioni di richiesta-sviluppo" .

composer install --no-dev

Nota: fai attenzione a tutto ciò che ha il potenziale per introdurre differenze tra sviluppo e produzione! In genere cerco di evitare il requisito di sviluppo laddove possibile, poiché includere gli strumenti di sviluppo non è un grosso problema.


1
Questo in realtà non è corretto nei dettagli. Non è necessario verificare le composer.lockdipendenze degli sviluppatori. Avresti semplicemente eseguito composer install --no-deve otterrai solo le dipendenze regolari installate - in effetti, Composer rimuoverà anche tutte le dipendenze degli sviluppatori in questo passaggio.
Sven,

Se il mio locale composer.lockavesse dipendenze dev (e potenzialmente influenzasse le versioni dei pacchetti non-dev) allora vorrei aggiornarlo per riflettere come sarebbe in produzione. Questo ti costringe anche a correre composer install --no-devin produzione, così come l' composer installerrore. Tecnicamente penso che tu abbia ragione; questo non è richiesto, ma è un ulteriore livello di sicurezza, che mi piace.
dave1010,

Ok, scenario demo: la tua app richiede dev/toole prod/lib:~1.0. Il più recente prod / lib è 1.3, ma anche dev / tool richiede prod/lib:1.1.*. Risultato: installerai la versione 1.1.9 (la più recente del ramo 1.1.x) e la utilizzerai durante lo sviluppo. Direi che NON è sicuro aggiornare solo --no-dev, quindi includi il più recente prod / lib 1.3 e suppongo che tutto funzioni senza test. E forse il test è quindi impossibile a causa della mancanza di dev / tool. Suppongo che, poiché dev / tool non è necessario in produzione, non dovrebbe essere implementato, ma il software deve utilizzare prod / lib 1.1.9.
Sven,

Se lo stai usando, --no-devdevi testarlo localmente, come ho detto nella risposta. Consiglio comunque di non usarlo --no-devaffatto.
dave1010,

Quindi fondamentalmente suggerisci questo:, composer updatequindi fai un po 'di sviluppo, poi fai composer update --no-dev, quindi fai il test di rilascio, quindi spingi alla produzione e fai composer install --no-dev. Due problemi: 1. Non riesco a testare il rilascio senza dipendenze dello sviluppatore e 2. Non riesco ad installare con Git ad esempio in produzione.
Sven,

3

Sul server di produzione cambio titolo vendoravendor-<datetime> , e durante la distribuzione avrà due dirs vendor.

Un cookie HTTP fa sì che il mio sistema scelga il nuovo fornitore autoload.php e dopo il test eseguo un passaggio completamente atomico / istantaneo tra loro per disabilitare la vecchia directory del fornitore per tutte le richieste future, quindi elimino la directory precedente qualche giorno dopo.

Questo evita qualsiasi problema causato dalle cache del filesystem che sto usando in apache / php, e consente anche a qualsiasi codice PHP attivo di continuare a utilizzare la precedente directory del fornitore.


Nonostante le altre risposte che lo raccomandano, corro personalmente composer install sul server, poiché questo è più veloce di rsync dalla mia area di gestione temporanea (una macchina virtuale sul mio laptop).

Io uso --no-dev --no-scripts --optimize-autoloader. Dovresti leggere i documenti per ognuno per verificare se questo è appropriato per il tuo ambiente.


2

Penso che sia meglio automatizzare il processo:

Aggiungi il file composer.lock nel tuo repository git, assicurati di usare composer.phar install --no-dev quando rilasci, ma nella tua macchina dev puoi usare qualsiasi comando compositore senza preoccupazioni, questo non andrà in produzione, il la produzione baserà le sue dipendenze nel file di blocco.

Sul server esegui il checkout di questa versione o etichetta specifica ed esegui tutti i test prima di sostituire l'app, se i test superano la distribuzione continua.

Se il test dipende dalle dipendenze dello sviluppatore, poiché il compositore non ha una dipendenza dall'ambito del test, una soluzione non molto elegante potrebbe essere eseguita con le dipendenze dello sviluppatore ( installazione composer.phar ), rimuovere la libreria del fornitore, eseguire composer.phar install - -no-dev nuovo, questo utilizzerà dipendenze memorizzate nella cache, quindi è più veloce. Ma questo è un trucco se conosci il concetto di ambiti in altri strumenti di costruzione

Automatizza questo e dimentica il resto, vai a bere una birra :-)

PS .: Come nel muggito del commento @Sven, non è una buona idea non controllare il file composer.lock, perché questo farà funzionare l'installazione del compositore come aggiornamento del compositore.

Potresti fare quella automazione con http://deployer.org/ è uno strumento semplice.


2
Non impegnarsi e fare il check-out composer.lockfarà composer installagire come composer update. Quindi le versioni che distribuisci non sono quelle con cui hai sviluppato. Ciò potrebbe generare problemi (e ancora di più alla luce del solo problema di sicurezza recentemente risolto con "sostituisci" in Composer). Non dovresti MAI correre composer updateincustodito senza verificare che non si sia rotto nulla.
Ser

1
@ Anche questo è un suggerimento nello stesso commento per eseguire automaticamente i test unitari prima della distribuzione. Ma hai ragione, è meglio conservare comunque il file composer.lock.
Giovanni Silva,

Ora l'unica cosa che dovresti spiegare: come esegui i test sul server senza le dipendenze degli sviluppatori come PHPUnit?
Sven,

Sarebbe molto bello se dipendenze, test e distribuzione fossero riuniti in un unico strumento, come Java Gradle o SBT o persino Maven (maven non è così buono). Uno strumento PHP che consente al phpunit del compositore e alla distribuzione di lavorare insieme. O anche un plug-in SBT Gradle o Scala per realizzare queste cose, poiché sono strumenti di generazione agnostici, il plug-in potrebbe persino funzionare con risorse come minimizzare javascript e compilare sass, minimizzare css. Qualcuno sa qualcosa?
Giovanni Silva,

1
Naturalmente questo viene fatto nel server per testare l'ambiente reale, ma non direttamente nel vhost del sito, è possibile farlo in una cartella temporanea separata e spostare il risultato nel vhost in caso di successo
Giovanni Silva
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.