Deployment PHP aplikací pomocí Deployeru a Gitlab CI
Jednoduchý návod na snadný deployment PHP/Symfony aplikací z Gitlabu i z lokálního počítače.
Nasazení nové verze aplikace bývá rutinní sled mnoha kroků a nebývá dobré na některý z nich zapomenout. To může být trochu složitější v situacích, kdy se třeba mění vlastnosti u dat neverzovaných v repozitářích - např. práva zápisu nebo struktura u dat aplikace.
Ideální řešení je tedy celý proces co nejvíce zautomatizovat, zakomponovat jej do vývojového procesu a učinit jej v něm snadno a rychle dostupný. Pokud provozujete vaší aplikaci v nějakém container enginu, tak pro její deployment pravděpodobně využíváte některý z nástrojů pro orchestraci kontejnerů. Pokud ale provozujete aplikaci klasickým způsobem, můžete automatizovaného deploymentu snadno dosáhnout např. jednoduchým Bash skriptem a nastavením možností jeho vzdáleného spouštění. Nám se ale pro tento způsob nasazování nových verzí Symfony aplikací asi nejvíce osvědčil nástroj Deployer.
Následující návod přidá možnost ručního spuštění deploymentu z Gitlabu pomocí CI a z lokálního počítače s naklonovaným repozitářem.
Deployer
Jako první krok přidáme do repozitáře phar soubory deployeru a composeru. Byť na stránkách deployer.org zkracují název souboru na prosté dep, doporučuji jej ponechat s koncovkou .phar. V PhpStormu pak bude možné rozkliknout jeho obsah a jednoduše sprojít a prozkoumat všechny různé 'recepty' pro různé frameworky a situace.
$ curl -LO https://deployer.org/deployer.phar
Poté již stačí vytvořit jednoduchý skript deploy.php
s popisem jednotlivých kroků pro spuštění aplikace a v jakém pořadí se mají spustit. Pro pořádek uvedu, že v rámci předpřipravených receptů není k dispozici konkrétní recept pro aktuální Symfony5. Nasazování aplikací se ale nijak neliší od Symfony4 a proto lze jednoduše vyžít recept pro tuto verzi. Níže uvedený recept je nutné v konkrétních detailech (repo url, sdílené soubory a adresáře, zapisovatelné adresáře atd.) upravit dle konkrétních potřeb.
<?php
namespace Deployer;
require 'recipe/symfony4.php';
set('application', 'iD-SIGN Website');
set('repository', 'ssh://git@gitlab.url/your/repo');
set('shared_dirs', ['var/log', 'var/sessions', 'public/media', 'data']);
set('shared_files', ['.env.local', 'public/robots.txt']);
set('writable_dirs', ['public/media', 'data', 'var/cache']);
set('bin/composer', '{{release_path}}/composer.phar');
set('keep_releases', 3);
// Hosts
host('production')
->hostname('yourserver.com')
->user('user')
->set('deploy_path', '/var/www/id-sign.com/www')
->set('http_user', 'www-data')
->become('id-sign');
// Tasks
task('deploy:build_assets', static function () {
run('cd {{release_path}} && yarn install && yarn encore production');
});
// Migrate database before symlink new release.
before('deploy:symlink', 'database:migrate');
before('database:migrate', 'deploy:build_assets');
// [Optional] if deploy fails automatically unlock.
after('deploy:failed', 'deploy:unlock');
Samotný skript je asi samovysvětlující. Pro rychlejší pochopení bez nutnosti studování kódu ještě připojím seznam úkolů, které definuje a spouští recept pro Symfony4 v rámci úkolu 'deploy'.
desc('Deploy project');
task('deploy', [
'deploy:info',
'deploy:prepare',
'deploy:lock',
'deploy:release',
'deploy:update_code',
'deploy:shared',
'deploy:vendors',
'deploy:writable',
'deploy:cache:clear',
'deploy:cache:warmup',
'deploy:symlink',
'deploy:unlock',
'cleanup',
]);
Jak to celé funguje? Deployer se skrze ssh spojení připojí na hostname() server jako user(). Pokud je potřeba se následně přepnout na jiného uživatele, nastaví se tento pomocí metody become() a k přepnutí se defaultně využívá sudo. Je potřeba tedy mít tuto možnost přepnutí user() -> become() povolenou.
Nastavení sudo je jednoduché, stačí přidat konfigurační soubor do /etc/sudoers.d
- např. /etc/sudoers.d/projectname a do něj uvést jednoduchý zápis a reloadnout sudo. Ukázka nastavení pro umožnění uživateli newman přepnutí se bez hesla na uživatele id-sign a tomu pak možnost přepnutí se na uživatele www-data.
newman ALL=(id-sign) NOPASSWD:ALL
id-sign ALL=(www-data) NOPASSWD:ALL
Že vše funguje ověříte velmi snadno např. pomocí:
newman@server$ sudo -u id-sign bash
Před prvním testovacím spuštěním uvedu, že deployer si na serveru vytváří vlastní adresářovou strukturu pro jednotlivé vydání. Pokud tedy již aplikaci máte nainstalovanou na serveru, bude velmi pravděpodobně nutné upravit její umístění a rovněž tak nastavení web serveru.
První pokusy doporučuji provádět mimo produkční verzi :-)
Testovací spuštění můžeme provést z lokálního počítače z adresáře s naklonovaným projektem. Pro plný komfort je vhodné mít nastaveno přihlašování na server pomocí ssh klíče. Pokud to nemáte, lze to velmi jednoduše napravit.
Vygenerování ssh klíče:
$ ssh-keygen
Instalace klíče na server (server uživatele a hostname serveru si upravte dle vaší situace):
$ ssh-copy-id user@your-server.com
Nyní již můžeme zkusit váš první deploy, který může vypadat takto:
$ php deployer.phar deploy production
✈︎ Deploying master on production
✔ Executing task deploy:prepare
✔ Executing task deploy:lock
✔ Executing task deploy:release
✔ Executing task deploy:update_code
✔ Executing task deploy:shared
✔ Executing task deploy:vendors
✔ Executing task deploy:writable
✔ Executing task deploy:cache:clear
✔ Executing task deploy:cache:warmup
✔ Executing task deploy:build_assets
✔ Executing task database:migrate
✔ Executing task deploy:symlink
✔ Executing task deploy:unlock
✔ Executing task cleanup
Successfully deployed!
Pokud by během procesu deploymentu nastala chyba, bude vás Deployer poměrně srozumitelně informovat. Pokud vše proběhlo v pořádku, tak byste měli mít na serveru v adresáři pro aplikaci vytvořenou novou strukturu adresářů:
$ ls -l
celkem 8
lrwxrwxrwx 1 id-sign id-sign 10 čec 9 13:15 current -> releases/1
drwxr-xr-x 8 id-sign id-sign 4096 čec 9 13:17 releases
drwxr-xr-x 5 id-sign id-sign 4096 lis 18 2020 shared
Nastavení webového serveru upravíte tak, aby document root ukazoval do public adresáře v adresáři current. Pokud by něco z výše uvedeného nebylo jasné, nebo vás zajímaly všechny možnosti nastavení, doporučuji si projít deployer dokumentaci
Gitlab CI
Pro deployment můžeme využít i Gitlab tak, abychom mohli nasadit nové verze přímo z jeho webového rozhraní. Oceníte to, pokud je součástí vaší práce třeba kontrola slučování různých vývojových větví do main větve a její následný release. Vše lze samozřejmě nastavit automaticky po úspěšném běhu testů, lintu atd. V této ukázce bude ale pro jednoduchost konfigurován manuální release. Ten si lze pak snadno upravit dle potřeb.
Jako první krok přidáme do repozitáře soubor .gitlab-ci.yml
s tímto obsahem (server hostname a php verzi upravímr dle potřeby):
stages:
- deploy
deploy:
image: chialab/php:8.0
stage: deploy
script:
- eval "$(ssh-agent -s)"
- ssh-add <(echo "$DEPLOY_KEY" | openssl base64 -A -d)
- mkdir ~/.ssh && ssh-keyscan -H your.server.com >> ~/.ssh/known_hosts
- php ./deployer.phar deploy production --branch $CI_COMMIT_REF_NAME -vv
when: manual
Dále v Gitlabu v nastavení repozitáře Settings -> CI/CD vytvoříme maskovanou proměnnou DEPLOY_KEY do které si uložíme base64 string ssh privátního klíče, kterým se budeme přihlašovat na server. Z bezpečnostních důvodů nechceme, aby byl privátní klíč pro přihlášení na server součástí repozitáře. Base64 string získáme snadno buďto v nějaké online službě, nebo v linuxu příkazem base64. Abychom mohli proměnnou v Gitlabu maskovat, musí být její hodnota jednořádková - parametrem -w 0
vypneme zalamování generovaného textu:
$ base64 -w 0 private.key > private64
Obsah vzniklého souboru zkopírujeme a uložíme jej do výše zmíněné proměnné DEPLOY_KEY.
A to je v podstatě vše. Nyní by se vám v rámci Gitlabu měla zobrazovat možnost pro spuštění CI deploy jobu a pokud máte k repozitáři i dostupné CI pipeline, mělo by vše bez problémů proběhnout a vy tak získáte možnost pustit deploy třeba ihned po sloučení změn z různých větví do hlavní větve, aniž byste museli pouštět příkazovou řádku a přihlašovat se na server.
Mohlo by vás také zajímat
Sentry Performance, PHP a GraphQL
Jak využít Sentry Performance pro monitoring výkonu PHP aplikace včetně výkonu GraphQL API.
Číst vícePHP8.1, Enum třídy a Doctrine
Jednou z novinek PHP8.1 je i podpora Enum tříd. Tento zápisek vznikl jako stručné intro k tomu, jak lze tuto novinku používat ve spojení s Doctrine.
Číst víceSymfony, lokální server a důvěryhodný SSL certifikát v Chrome
Nastavte si důvěryhodný certifikát v Chrome i pro vývoj Symfony aplikací
Číst vícePotřebujete více informací?
Zpráva byla úspěšně odeslána.
Děkujeme
Omlouváme se, ale zprávu se nepovedlo odeslat.
Budeme rádi, když nám o tomto dáte vědět na info@id-sign.com