Deployer – proste narzędzie do deployowania
Dziś będzie o prostym narzędziu, które automatyzuje proces wdrażania strony/aplikacji na serwer produkcyjny.
Zanim przejdę do rzeczy, wyobraź sobie następującą sytuację.
Od dłuższego czasu pracujesz nad nową wersją strony, aż po wielu tygodniach hardcorowego kodowania dochodzisz
do etapu, kiedy wszystko działa zgodnie z oczekiwaniami, wszystkie testy świecą się na zielono, a klient podejmuje decyzję,
że stronę trzeba wgrać na produkcję.
I wtedy zjawia się szef i mówi:
Kiedy nadchodzi moment deployu, mówisz – nadejszła wiekopomna chwila, logujesz się na serwer i odpalasz słynne
git pull
. Chwilę potem wchodzisz na stronę i odkrywasz, że strona klienta się s*****oliła.
Co można zrobić w takiej sytuacji? Najlepiej jak najszybciej przywrócić stronę do poprzedniej wersji, ale okazuje się, że zapomniałeś zrobić kopii. Głowisz się nad tym, jaki był ostatni działający commit, a czas leci. Jednym słowem armagedon.
Cała ta sytuacja jest oczywiście zmyślona, jednak uzmysławia, że czynności związane z wgrywaniem aplikacji, powinny być w jak największym stopniu zautomatyzowane. Przy ręcznym wgrywaniu zawsze można pomylić się albo o czymś zapomnieć. Poza tym zawsze powinno dać się cofnąć do ostatniej działającej wersji.
Żeby uniknąć podobnych sytuacji, warto skorzystać z narzędzia o nazwie Deployer.
Jak zainstalować deployera
Oficjalna dokumentacja mówi, że należy wprowadzić do konsoli następujące komendy:
curl -LO https://deployer.org/deployer.phar
mv deployer.phar /usr/local/bin/dep
chmod +x /usr/local/bin/dep
Po zainstalowaniu deployera można utworzyć skrypt o nazwie deploy.php
.
Aby to zrobić, wystarczy wydać komendę:
dep init
Po uruchomieniu komendy dep init
zostaniesz poproszony o wybór rodzaju projektu:
Bez względu na to, z jakim rodzajem aplikacji mamy do czynienia, polecam wybrać pierwszą opcję tj.
Common
. Nawet jeśli projekt jest zrobiony w jakimś konkretnym frameworku np. w Symfony,
to i tak o tym, co powinno zostać zrobione przy wgrywaniu aplikacji, powinniśmy decydować my. Dlatego właśnie
opcja Common
, wydaje się najbezpieczniejszą opcją, ponieważ domyślnie ogranicza się jedynie do
podstawowych operacji takich jak kopiowanie plików z repozytorium.
Konfiguracja
Rzeczą, od której należy zacząć, jest ustawienie parametru repository
. Określa on adres repozytorium
git, z którego będzie zaciągany kod aplikacji.
set('repository', 'git@gitlab.com:john/hello.git');
Deployer domyślnie przełącza projekt na gałąź master. Jednak nie jest to jedyne słuszne ustawienie i można je zmienić
za pomocą parametru branch
.
set('branch', 'my_branch');
Deployer tworzy katalog shared
, w którym trzymane są pliki i foldery współdzielone pomiędzy
poszczególnymi wydaniami. Do takich plików możemy zaliczyć np. ilustracje zamieszczone w artykułach na stronie
i pliki konfiguracyjne aplikacji. Dzięki temu katalogowi możemy być spokojni o to,
że określone pliki nie zostaną naruszone podczas wgrywania nowej wersji.
Do definiowania katalogów współdzielonych służy parametr shared_dirs
:
set('shared_dirs', [
'app/config',
'public/images'
]);
Istnieje również możliwość współdzielenia pojedynczych plików. Przykładem takiego pliku może być plik weryfikacyjny domeny w Google Search Console:
set('shared_files', [
'public/googleaWfDU5y6snaR6YuL.html',
]);
Niektóre z katalogów powinny mieć ustawiony taki poziom uprawnień, który gwarantuje, że aplikacja
będzie miała prawa do zapisu. W tym celu należy ustawić parametr writable_dirs
:
set('writable_dirs', [
'vendor',
]);
Rzeczą, która koniecznie musi znaleźć się w pliku konfiguracyjnym jest task o nazwie deploy
:
task('deploy', [
// taski, które wykonują się przy deployu
]);
W powyższym przykładzie należy podać tablicę z nazwami tasków, które będą wykonywane
za każdym razem, gdy w konsoli zostanie wydana komenda dep deploy
.
Przykładowy plik konfiguracyjny deployera (deploy.php
) może wyglądać tak:
<?php
namespace Deployer;
require 'recipe/common.php';
// Project name
set('application', 'my_project');
// Project repository
set('repository', 'git@gitlab.com:john/hello.git');
// [Optional] Allocate tty for git clone. Default value is false.
set('git_tty', true);
// Shared files/dirs between deploys
set('shared_files', [
'public/googleaWfDU5y6snaR6YuL.html',
]);
set('shared_dirs', [
'app/config',
'public/images'
]);
// Writable dirs by web server
set('writable_dirs', [
'vendor',
]);
// Tasks
desc('Deploy your project');
task('deploy', [
'deploy:info',
'deploy:prepare',
'deploy:lock',
'deploy:release',
'deploy:update_code',
'deploy:shared',
'deploy:writable',
'deploy:vendors',
'deploy:clear_paths',
'deploy:symlink',
'deploy:unlock',
'cleanup',
'success'
]);
// [Optional] If deploy fails automatically unlock.
after('deploy:failed', 'deploy:unlock');
Wgrywanie aplikacji
Wgrywanie sprowadza się to wydania komendy dep deploy
. Poprawnie skonfigurowany Deployer
zapewnia ochronę przed uszkodzeniem aktualnie działającej wersji. Jeżeli podczas wykonywania, któregoś z tasków
wystąpi błąd, możemy być spokojni o to, że aktualna wersja aplikacji nie zostanie nadpisana.
Ważną cechą deployera jest możliwość cofnięcia się do poprzedniej wersji w razie, gdyby okazało się, że
nie wszystko działa tak jak powinno. W tym celu wystarczy wydać komendę dep rollback
.
Struktura katalogów
W katalogu releases
znajdują się wszystkie dostępne wydania, a ich liczba jest ograniczona
przez parametr konfiguracyjny keep_releases
.
Plik current
jest dowiązaniem symbolicznym do ostatniej działającej wersji, czyli folderu
znajdującego się w katalogu releases
.
Jest on aktualizowany za każdym razem, kiedy proces wgrywania kończy się powodzeniem. Podobnie dzieje się
w przypadku cofania się do poprzedniej wersji.
Katalog shared
był już przeze mnie omawiany, jednak powtórzę, że służy on do przechowywania plików,
które mają być współdzielone pomiędzy różnymi wydaniami.
Podsumowanie
Deployer jest prostym i skutecznym narzędziem, które zmniejsza ryzyko pomyłki przy wgrywaniu aplikacji na serwer. Sądzę, że warto poświęcić odrobinę czasu na poznanie tego, bądź innego narzędzia przeznaczonego do deploymentu. Z pewnością pozwoli to na zaoszczędzenie czasu i nerwów w przyszłości.