Strona Główna Blog webmasterski

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:

Ekran konsoli po uruchomieniu komendy dep init

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

Deployer - struktura katalogów
Ilustracja przedstawia strukturę katalogów utworzoną przez Deployera.

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.