Jak prawidłowo wdrożyć, korzystając z przełącznika programistycznego / produkcyjnego Composera?

180

Composer ma możliwość załadowania kilku zależności tylko podczas opracowywania, więc narzędzia nie zostaną zainstalowane w środowisku produkcyjnym (na serwerze rzeczywistym). Jest to (w teorii) bardzo przydatne w przypadku skryptów, które mają sens tylko w programowaniu, takich jak testy, narzędzia do fałszywych danych, debugger itp.

Najlepszym sposobem jest dodanie dodatkowego require-devbloku z narzędziami potrzebnymi w programie deweloperskim:

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

a następnie (teoretycznie) załaduj te zależności za pośrednictwem

composer install --dev

Problem i pytanie:

Composer zmienił zachowanie installi updateradykalnie w 2013 roku, require-dev-zależności są teraz instalowane domyślnie (!), Możesz swobodnie utworzyć plik composer.json z require-devblokiem i wykonać go composer installdo odtworzenia.

Ponieważ najbardziej akceptowanym sposobem wdrażania jest wypchnięcie kompozytora. lock (który przechowuje twoją obecną konfigurację kompozytora), a następnie wykonaj composer installna serwerze produkcyjnym, to również zainstaluje programowanie.

Jaki jest prawidłowy sposób wdrożenia tego bez instalowania zależności -dev?

Uwaga: próbuję tutaj utworzyć kanoniczne pytania / odpowiedzi, aby wyjaśnić dziwne wdrożenie kompozytora. Zapraszam do edycji tego pytania.

Sliq
źródło
@all: Nie wiem, gdzie jest nagroda :( Zacznę od innego podejścia.
Sliq
1
Jeśli nie nagrodzisz go aktywnie i żadna odpowiedź nie zostanie zaakceptowana lub nie otrzyma wystarczającej liczby pozytywnych głosów, nikt nie otrzyma nagrody.
Sven
2
Osobiście w ogóle nie lubię tego podejścia. composer.lockNigdy nie powinny być dodawane do repo Git, nigdy. Właściwym podejściem jest użycie aktualizacji kompozytora podczas przemieszczania, a następnie zsynchronizowanie pliku z produkcją (jeśli oczywiście wszystko działa). Inscenizacja musi być dokładną kopią środowiska produkcyjnego. composer.lockpowinien być częścią .gitignore.
rzeczownik
6
Kompozytor.lock musi być na pewno zawarty w twoim CSV !!! Jak inaczej można się upewnić, że wszyscy używają tej samej wersji? Dlatego NIGDY nie wykluczaj pliku composer.lock z pliku CSV !!!
Tobias Gaertner
3
@TobiasGaertner Myślę, że masz na myśli VCS (oprogramowanie do kontroli wersji), ale poza tym jesteś poprawny i zgodny z oficjalnymi zaleceniami projektu .
Xiong Chiamiov

Odpowiedzi:

327

Czemu

IMHO ma dobry powód, dla którego obecnie Composer będzie używał tej --devflagi domyślnie (podczas instalacji i aktualizacji). Composer jest najczęściej uruchamiany w scenariuszach, w których jest to pożądane zachowanie:

Podstawowy przepływ pracy Composer wygląda następująco:

  • Rozpoczyna się nowy projekt: composer.phar install --devpliki json i lock są przekazywane do VCS.
  • Inni programiści rozpoczynają pracę nad projektem: checkout VCS i composer.phar install --dev.
  • Programista dodaje zależności: composer.phar require <package>dodaj, --devjeśli chcesz, aby pakiet znalazł się w require-devsekcji (i zatwierdź).
  • Inni idą razem: (kasy i) composer.phar install --dev.
  • Deweloper chce nowszych wersji zależności: composer.phar update --dev <package>(i commit).
  • Inni idą razem: (kasy i) composer.phar install --dev.
  • Projekt jest wdrażany: composer.phar install --no-dev

Jak widać, --devflaga jest używana (znacznie) częściej niż --no-devflaga, zwłaszcza gdy rośnie liczba programistów pracujących nad projektem.

Wdrożenie produkcyjne

Jaki jest prawidłowy sposób wdrożenia tego bez instalowania zależności „dev”?

Cóż, plik composer.jsoni composer.lockpowinien zostać zatwierdzony do VCS. Nie pomijaj, composer.lockponieważ zawiera ważne informacje o wersjach pakietów, które powinny być używane.

Podczas wdrażania produkcyjnego możesz przekazać --no-devflagę do Composera:

composer.phar install --no-dev

composer.lockPlik może zawierać informacje o dev-pakietów. To nie ma znaczenia. --no-devFlag zadba te dev-pakiety nie są zainstalowane.

Kiedy mówię „wdrożenie produkcyjne”, mam na myśli wdrożenie, którego celem jest wykorzystanie w produkcji. Nie spieram się, czy composer.phar installnależy to zrobić na serwerze produkcyjnym, czy na serwerze pomostowym, na którym można sprawdzić. To nie jest zakres tej odpowiedzi. Po prostu wskazuję, jak to zrobić composer.phar installbez instalowania zależności „dev”.

Poza tematem

--optimize-autoloaderFlaga może być również pożądane na produkcji (generuje klasy mapę, która przyspieszy samoładownicze w aplikacji):

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

Lub po zakończeniu automatycznego wdrażania:

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

Jeśli Twój kod obsługuje to, możesz zamienić --optimize-autoloaderna --classmap-authoritative. Więcej informacji tutaj

Jasper N. Brouwer
źródło
5
Zgadzam się z większością tego, co zostało powiedziane, z jednym wyjątkiem. Polecenie „composer install --no-dev” powinno być wykonywane tylko w środowisku pomostowym i należy je uważać za niezmienne. Nie chciałbym pobierać żadnych zależności bezpośrednio na mój serwer produkcyjny bez przechodzenia przez podgląd / staging. To tylko dodatkowa ostrożność.
Skalowalne
3
@Scalable: Chociaż zgadzam się z tobą (a Sven ładnie to ujął w swojej odpowiedzi), to nie jest zakres mojej odpowiedzi, a nie to, co miałem na myśli mówiąc o „wdrożeniu produkcyjnym”. Dodałem akapit, aby to wyjaśnić.
Jasper N. Brouwer
5
Właściwie uważam, że opcja domyślna powinna być mniej niebezpieczną opcją. Ustawienie opcji --dev jako domyślnej i przypadkowe wykonanie instalacji kompozytora w środowisku produkcyjnym może być fatalne w skutkach.
Hector Ordonez
3
Dobra uwaga w --optimize-autoloader. Weź również pod uwagę --classmap-authoritative- z dokumentacji tutaj getcomposer.org/doc/03-cli.md można zobaczyć: „Automatyczne ładowanie klas tylko z mapy klas. Niejawnie włącza --optimize-autoloader”, więc możesz użyć, jeśli znasz klasy ” there ", co prawdopodobnie powinno się zdarzyć w środowisku produkcyjnym, chyba że klasy są generowane dynamicznie.
Xavi Montero
6
Świetna odpowiedź, sugerowałbym dodanie optimize-autoloaderbezpośrednio w composer.json:{"config": { "optimize-autoloader": true } }
Yvan
79

Właściwie to zdecydowanie poleciłbym PRZECIWKO instalowaniu zależności na serwerze produkcyjnym.

Zalecam pobranie kodu na maszynie wdrożeniowej, zainstalowanie zależności w razie potrzeby (obejmuje to NIE instalowanie zależności dev, jeśli kod trafi do produkcji), a następnie przeniesienie wszystkich plików na maszynę docelową.

Czemu?

  • w przypadku hostingu współdzielonego dostęp do wiersza poleceń może być niemożliwy
  • nawet jeśli tak, PHP może być tam ograniczone w zakresie poleceń, pamięci lub dostępu do sieci
  • narzędzia CLI repozytorium (Git, Svn) prawdopodobnie nie zostaną zainstalowane, co mogłoby się nie udać, gdyby plik blokady zarejestrował zależność do wypisania określonego zatwierdzenia zamiast pobierania tego zatwierdzenia jako ZIP (użyłeś --prefer-source lub Composer nie ma innego sposobu na uzyskanie tej wersji)
  • jeśli twoja maszyna produkcyjna bardziej przypomina mały serwer testowy (pomyśl o mikro instancji Amazon EC2), prawdopodobnie nie ma nawet wystarczającej ilości pamięci zainstalowanej do wykonania composer install
  • Podczas gdy composer nie próbuje niczego zepsuć, co myślisz o zakończeniu częściowo zepsutej witryny produkcyjnej, ponieważ nie można było załadować jakiejś losowej zależności podczas fazy instalacji Kompozytorów

Krótko mówiąc: korzystaj z Composera w środowisku, które możesz kontrolować. Twoja maszyna programistyczna kwalifikuje się, ponieważ masz już wszystko, co jest potrzebne do obsługi programu Composer.

Jaki jest prawidłowy sposób wdrożenia tego bez instalowania zależności -dev?

Polecenie do użycia to

composer install --no-dev

To zadziała w każdym środowisku, czy to na samym serwerze produkcyjnym, na maszynie wdrożeniowej, czy też na maszynie deweloperskiej, która ma wykonać ostatnią kontrolę, aby stwierdzić, czy jakiekolwiek wymagania programistyczne nie są nieprawidłowo używane w rzeczywistym oprogramowaniu.

Polecenie nie zainstaluje ani aktywnie odinstaluje wymagań programistycznych zadeklarowanych w pliku composer.lock.

Jeśli nie masz nic przeciwko wdrażaniu komponentów oprogramowania deweloperskiego na serwerze produkcyjnym, uruchomienie composer installwykonałoby to samo zadanie, ale po prostu zwiększyłoby ilość przenoszonych bajtów, a także utworzyło większą deklarację autoloadera.

Sven
źródło
14
Ciekawy przepływ pracy, ale jest duży minus : repozytoria nigdy nie powinny zawierać samego folderu / zawartości dostawcy (oficjalne oświadczenia na stronie Composer), więc nigdy nie zostaną bezpośrednio przeniesione do produkcji we wdrożeniu opartym na git (co jest powszechnym standardem afaik, Popraw mnie, jeśli się mylę). Więc w zasadzie powyższe rozwiązanie działa tylko z "oldschoolowym" wdrożeniem FTP!? Przedyskutujmy to dalej ...
Sliq
17
Mój sugerowany przepływ pracy nie obejmuje wypychania kodu przez GIT na serwer produkcyjny. Właściwie odradzałbym to, ponieważ zmusi cię to do zainstalowania zależności Composera na serwerze produkcyjnym, co może wywołać dowolną liczbę problemów. Jeśli chcesz, aby wdrożenie przebiegało sprawnie, musisz zebrać cały kod potrzebny do uruchomienia aplikacji, zanim zniszczysz bieżącą wersję i zastąpisz ją. Nie lubisz FTP? RSync przez SSH, a następnie przełączaj wersje, odwracając łącze symboliczne. Ale jeśli chcesz, możesz także wypchnąć, wyewidencjonować i zainstalować kompozytor w wersji prod.
Sven
2
@Panique: Właśnie zobaczyłem tę część twojego komentarza i muszę odpowiedzieć: „przeniesiony do produkcji we wdrożeniu opartym na git (co jest powszechnym standardem afaik, popraw mnie, jeśli się mylę)” - Nie, to nie jest powszechnym standardem. To tylko jeden sposób.
Sven
1
Zespół, w którym pracuję, z wielkim sukcesem włączył to do swojego przepływu pracy. Mamy maszynę do budowania (oczywiście Jenkins), która: 1) pobiera oprogramowanie z SC 2) uruchamia instalację / aktualizację kompozytora 3) wykonuje testy jednostkowe 4) usuwa zależności od programistów 5) generuje plik phar ( app-1.34.pharitp.). Istnieje oddzielny mechanizm, który jest powiadamiany i decyduje, kiedy pobrać ten plik, gdzie go przesłać, a następnie co z nim zrobić. Niektóre zespoły decydują się na rozpakowanie phara po umieszczeniu go na serwerze, a niektóre obsługują go tak, jak jest. Dało to duże zaufanie do stabilności i odtwarzalności naszych wdrożeń.
Josh Johnson,
3
Zgadzam się w 100% z tą odpowiedzią. Composer nie powinien być instalowany na serwerze wdrażania ani git. Serwery Continuous Deployment / Intergration mają dokładnie zarządzać pobieraniem źródła i zależności: git pull> composer install> deploy
Eric MORAND
4

Teraz require-devjest domyślnie włączony, w przypadku lokalnego programowania można to zrobić composer installi composer updatebez tej --devopcji.

Jeśli chcesz wdrożyć w środowisku produkcyjnym, musisz upewnić się, composer.lockże nie ma żadnych pakietów, które pochodzą z require-dev.

Możesz to zrobić za pomocą

composer update --no-dev

Po przetestowaniu lokalnie --no-devmożesz wdrożyć wszystko do produkcji i zainstalować w oparciu o composer.lock. Potrzebujesz tej --no-devopcji ponownie, w przeciwnym razie kompozytor powie "Plik blokujący nie zawiera informacji require-dev" .

composer install --no-dev

Uwaga: uważaj na wszystko, co może powodować różnice między programowaniem a produkcją! Generalnie staram się unikać require-dev, gdy tylko jest to możliwe, ponieważ dołączenie narzędzi programistycznych nie jest dużym narzutem.

dave1010
źródło
1
W szczegółach jest to faktycznie nieprawidłowe. Nie ma potrzeby sprawdzania composer.lockzależności deweloperskich. Po prostu uruchomisz composer install --no-dev, a zainstalujesz tylko zwykłe zależności - w rzeczywistości Composer usunie również wszelkie zależności dev w tym kroku.
Sven
Gdyby mój lokalny composer.lockplik zawierał zależności deweloperskie (i potencjalnie wpływał na wersje pakietów innych niż deweloperskie), chciałbym go zaktualizować, aby odzwierciedlić, jak będzie w produkcji. To również zmusza cię do pracy composer install --no-devw produkcji, podobnie jak composer installbłąd. Technicznie myślę, że masz rację; nie jest to wymagane, ale jest to dodatkowy poziom bezpieczeństwa, który mi się podoba.
dave1010,
OK, scenariusz demonstracyjny: Twoja aplikacja wymaga dev/tooli prod/lib:~1.0. Najnowszy prod / lib to 1.3, ale dev / tool również wymaga prod/lib:1.1.*. Wynik: zainstalujesz wersję 1.1.9 (najnowszą z gałęzi 1.1.x) i będziesz jej używać podczas tworzenia. Powiedziałbym, że NIE jest bezpieczna aktualizacja --no-dev, dlatego dołącz najnowszą wersję prod / lib 1.3 i zakładaj, że wszystko działa bez testowania. A może wtedy testowanie jest niemożliwe z powodu braku dev / tool. Zakładałbym, że ponieważ dev / tool nie jest potrzebne w produkcji, nie należy go wdrażać, ale oprogramowanie musi wtedy używać prod / lib 1.1.9.
Sven
Jeśli używasz --no-dev, musisz go przetestować lokalnie, jak wspomniałem w odpowiedzi. Nadal jednak polecałbym --no-devw ogóle nie używać .
dave1010,
Zasadniczo sugerujesz to: composer updatenastępnie zrób coś programistycznego, następnie zrób composer update --no-dev, a następnie przeprowadź testy wydania, a następnie przejdź do produkcji i zrób composer install --no-dev. Dwa problemy: 1. Nie mogę przetestować wydania bez zależności deweloperskich i 2. Nie mogę zainstalować na przykład Gita w środowisku produkcyjnym.
Sven
3

Na serwerach produkcyjnych zmieniam nazwę vendorna vendor-<datetime>i podczas wdrażania będę mieć dwa katalogi dostawców.

Plik cookie HTTP powoduje, że mój system wybiera nowego dostawcę autoload.php, a po przetestowaniu wykonuję całkowicie atomowe / natychmiastowe przełączanie między nimi, aby wyłączyć katalog starego dostawcy dla wszystkich przyszłych żądań, a następnie usuwam poprzedni katalog kilka dni później.

Pozwala to uniknąć wszelkich problemów spowodowanych przez pamięci podręczne systemu plików, których używam w apache / php, a także pozwala każdemu aktywnemu kodowi PHP na kontynuowanie korzystania z katalogu poprzedniego dostawcy.


Pomimo innych odpowiedzi zalecających przeciwko temu, osobiście działam composer installna serwerze, ponieważ jest to szybsze niż rsync z mojego obszaru przejściowego (maszyna wirtualna na moim laptopie).

Używam --no-dev --no-scripts --optimize-autoloader. Powinieneś przeczytać dokumentację dla każdego z nich, aby sprawdzić, czy jest to odpowiednie dla twojego środowiska.

Abhi Beckert
źródło
2

Myślę, że lepiej zautomatyzować ten proces:

Dodaj plik composer.lock do repozytorium git, upewnij się, że używasz pliku composer.phar install --no-dev po wydaniu używasz , ale na swoim komputerze deweloperskim możesz bez obaw użyć dowolnego polecenia composer, to nie przejdzie do produkcji, produkcja oprze swoje zależności w pliku blokady.

Na serwerze pobierasz tę konkretną wersję lub etykietę i uruchamiasz wszystkie testy przed zastąpieniem aplikacji, jeśli testy zakończą się pomyślnie, kontynuujesz wdrażanie.

Jeśli test zależy od zależności dev, ponieważ kompozytor nie ma zależności zakresu testowego, niezbyt eleganckim rozwiązaniem może być uruchomienie testu z zależnościami dev ( instalacja composer.phar ), usunięcie biblioteki dostawcy, uruchomienie instalacji composer.phar - -no-dev ponownie, użyje buforowanych zależności, więc jest szybsze. Ale to hack, jeśli znasz pojęcie zakresów w innych narzędziach do kompilacji

Zautomatyzuj to i zapomnij o reszcie, idź napić się piwa :-)

PS .: Jak w komentarzu @Sven poniżej, nie jest dobrym pomysłem nie sprawdzanie pliku composer.lock, ponieważ spowoduje to, że instalacja narzędzia Composer będzie działać jako aktualizacja kompozytora.

Możesz zrobić tę automatyzację za pomocą http://deployer.org/ jest to proste narzędzie.

Giovanni Silva
źródło
2
Niezatwierdzenie się i wyewidencjonowanie composer.lockbędzie composer installdziałać jak composer update. Dlatego wdrażane wersje nie są tymi, które opracowałeś. Może to spowodować problemy (a tym bardziej w świetle jedynego niedawno rozwiązanego problemu z zabezpieczeniami polegającego na „zastąpieniu” w programie Composer). NIGDY nie powinieneś uruchamiać się composer updatebez nadzoru bez sprawdzenia, czy nic nie zepsuło.
Sven
1
@ Nawet w ten sposób sugeruje się w tym samym komentarzu automatyczne uruchamianie testów jednostkowych przed wdrożeniem. Ale masz rację, i tak lepiej zachowaj plik composer.lock.
Giovanni Silva
Teraz jedyne, co musiałbyś wyjaśnić: jak uruchomić testy na serwerze bez zależności deweloperskich, takich jak PHPUnit?
Sven
Byłoby bardzo fajnie, gdyby zależności, testy i wdrożenie zostały umieszczone razem w jednym narzędziu, takim jak Java Gradle lub SBT, a nawet Maven (maven nie jest taki dobry). Jedno narzędzie PHP, dzięki któremu phpunit kompozytora i wdrożenie współpracują ze sobą. Lub nawet wtyczka Gradle lub Scala SBT, aby to zrobić, ponieważ są one agnostycznymi narzędziami do kompilacji, wtyczka może nawet działać z zasobami, takimi jak minimalizacja javascript i kompilacja sass, minimalizacja css. Ktoś coś wie?
Giovanni Silva
1
Oczywiście odbywa się to na serwerze, aby przetestować rzeczywiste środowisko, ale nie bezpośrednio w witrynie vhost, możesz to zrobić w oddzielnym folderze tymczasowym i przenieść wynik do vhosta, gdy się powiedzie
Giovanni Silva,