Automatický deployment webu na FTP

Určitě stále platí, že nasazování webu pomocí FTP je jedním z nejrozšířenějších způsobů, se kterým se setkáte. Někdy to však může být pěkná otrava, především u projektů, které se průběžně vyvíjí a změny se na server nahrávají pravidelně. V těchto případech máte většinou na výběr buď zbytečně nahrát na FTP opět celý projekt (což mimo jiné bude i časově daleko náročnější) nebo ručně vybrat změněné soubory a nahrát pouze je, jeden po druhém, na FTP.

Druhý zmíněný soubor jsem sám dělal poměrně dlouho, ale neslo to s sebou několik nevýhod. První může být například to, že je zde reálná šance, že něco zapomenete nahrát. Dalším problémem může být třeba to, že soubory se nahrávají postupně za běhu aplikace, která se může na nějakou dobu stát nefunkční, protože soubory na sobě navzájem závisí.

Automatický PHP FTP deployment

Jednoduchým, ale plně funkčním řešením, je využití FTP deploymentu od Davida Grudla. Jedná se o PHP knihovnu, která Vám zajistí chytrý deployment změněných souborů na vzdálené FTP. Soubory se porovnávají pomocí MD5 hashe jednotlivých souborů a díky tomu se po spuštění deploymentu nahrávají opravdu jen ty změněné.

Důležitou funkcí, jakým způsobem nahrávání souborů probíhá, je i to, že soubory se nejdříve nahrají na FTP s příponou .deploytmp a teprve až se všechny nahrají, jsou přejmenovány na originální název. To oceníte především v případě, kdy nahráváte větší množství nebo velké soubory, jelikož samotné nahrávání souborů tím nebude brzdit běh aplikace a přejmenování souborů už je pak daleko rychlejší operace, než jejich nahrávání.

Jediné, co k použití potřebujete, je mít nainstalováno PHP (např. za pomocí Wampu) a v něm aktivováno rozšíření php_ftp.

Konfigurační soubor deployment.ini

Celý proces deploymentu si můžete nakonfigurovat v rámci jednoho souboru deployment.ini. Jediná povinná položka v něm je nakonfigurování remote serveru – nastavení FTP přístupů na vzdálený server. V případě složitější konfigurace tento soubor může ale vypadat i nějak takto:

; remote FTP server
remote = ftp://user:secretpassword@ftp.example.com/directory

; FTP passive mode
passiveMode = yes

; local path (optional)
local = ./

; run in test-mode? (can be enabled by option -t or --test too)
test = no

; files and directories to ignore
ignore = "
	/.htaccess
	log/
	temp/cache/*
	node_modules/
	deployment.*.*
"

; is allowed to delete remote files? (defaults to yes)
allowDelete = yes

; jobs to run before file upload
before[] = 'http://example.com/deploy/maintenance-mode-on.php?token=SET_UNIQUE_TOKEN'

; jobs to run after file upload
after[] = 'http://example.com/deploy/maintenance-mode-off.php?token=SET_UNIQUE_TOKEN'

; directories to purge after file upload
purge[] = temp/cache

; files to preprocess (defaults to *.js *.css)
preprocess = no

; file which contains hashes of all uploaded files (defaults to .htdeployment)
deploymentFile = .deployment

; default permissions for new files (defaults to none)
filePermissions = 0644

; default permissions for new directories (defaults to none)
dirPermissions = 0755

Kromě nastavení přístupů na FTP zde můžeme mimo jiné nastavit například i to, které soubory budou při deploymentu ignorovány, akce, které se spustí před spuštěním nahrávání souborů (zapnutí módu údržby na webu) a které se spustí po dokončení nahrávání (vypnutí módu údržby) nebo také smazání složky s cache aplikace. Kompletní možnosti konfigurace naleznete přímo v dokumentaci.

V rámci ignorovaných souborů je vhodné uvést všechny soubory a složky, které nejsou pro běh aplikace na serveru nutné. Můžou to být například zdrojové CSS a JS soubory před minifikací, složky s cache nebo logy, ale také konfigurační soubory a .htaccess soubory, které se můžou napříč prostředími lišit (tyto soubory je pak potřeba nahrávat ručně).

Testovací režim

Důležitá a často používaná je možnost nastavení testovacího režimu, k čemuž složí nastavení parametru test. Pokud je test = yes a spustíme deployment jako obvykle, můžeme vidět, které soubory se na FTP nahrají a které budou smazány – reálně se však nic neprovede. To se může určitě občas hodit, abychom se ujistili, že na FTP budou nahrány správné soubory a naopak se nám nesmaže nic důležitého, co si nepřejeme.

Nastavení deploymentu pro více serverů

Často se setkáme se situací, kdy pro jeden web máme více serverů – typicky vývojový (testovací) a produkční. Určitě nám nic nebrání si vytvořit dva konfigurační .ini soubory a využít právě ten, kam chceme soubory nahrávat. Problém ale je to, že spousta nastavení je pro oba servery stejné a dost často se budou lišit jen v přístupových údajích. A když si do toho ještě přidáme situaci, kdy není vhodné z bezpečnostních důvodů verzovat v GITu tyto konfigurační soubory s uloženými přístupy na FTP, je problém konfiguraci navzájem udržovat, ještě navíc, když na projektu pracuje více vývojářů. V reálu se pak stane, že když jeden vývojář změní konfiguraci a přidá například novou ignorovanou složku, druhý vývojář si toho nemusí všimnout a složku si do ignore nepřidá.

Řešení tohoto problému ale není nijak složité. Stále využíváme jeden hlavní deployment.ini soubor, ve kterém se nachází konfigurace, která bude vždy pro všechny servery stejná. Kromě toho si vytvoříme ještě jeden konfigurační soubor deployment.example.php, který bude vypadat takto:

<?php

$global = parse_ini_file('deployment.ini');

$local = [
	'remote'   => 'ftp://ftp.example.com/directory',
	'user'     => '',
	'password' => ''
];

return array_merge($global, $local);

Soubor nedělá nic jiného než to, že načte konfiguraci ze společného souboru deployment.ini a sloučí ji s konfigurací v lokálním souboru. V tomto případě už je zde předpřipraveno pole s konfigurací přístupů na FTP. Jelikož se však ani v jednom souboru nenachází reálné přístupy na FTP, není problém je verzovat v GITu.

Když si potom budu chtít nastavit deployment pro vývojový server, zkopíruji si soubor deployment.example.php a pojmenuji ho deployment.dev.php. Pro produkční server to může být například deployment.live.php. Do těchto souborů si už doplním funkční přístupy na dané FTP, soubory však budou v GITu ignorovány, abychom předešli bezpečnostním problémům a úniků přístupů na FTP.

Spuštění deploymentu souborů

Konečně se dostáváme k samotnému spuštění FTP deploymentu. V případě, že máme knihovnu nainstalovanou přes composer (což doporučuji), nejjednodušeji deployment spustíme příkazem:

php vendor/dg/ftp-deployment/deployment deployment.dev.php

Vytvoření composer scriptu

Druhou možností a mírným zjednodušením může být vytvoření nového scriptu v rámci sekce scripts souboru composer.json.

{
  "scripts": {
    "deploy:dev": "php vendor/dg/ftp-deployment/deployment deployment.dev.php"
  }
}

Deployment se pak spustí příkazem:

composer deploy:dev

FTP deployment za pomocí Gruntu

Třetí možností, kterou i jakožto frontend developer využívám nejčastěji, je využít Grunt. V Gruntu si vytvořím nový task, který mi před deploymentem spustí kompilací assetů (CSS, JS), nahraje soubory a po nahrání otevře v prohlížeči URL serveru, kam se web nahrál – takže hned vidím, zda aplikace běží a můžu ji otestovat.

grunt.registerTask('deployDev', ['compile', 'shell:deployDev', 'open:devURL']);

K tomuto využívám node balíčky grunt-shell grunt-open (k tomu samozřejmě úlohy pro kompilaci assetů). Konfigurace v gruntfile.js pak může vypadat takto:

open: {
	devURL: {
		path: 'https://example.com/'
	}
},
shell: {
	deployDev: {
		command: 'php vendor/dg/ftp-deployment/deployment deployment.dev.php'
	}
}

Celý proces pak spustím jednoduše příkazem (nebo ještě lépe přímo v PHP Stormu v seznamu Grunt úloh spustím deployment za pomocí kliknutí myší):

grunt deployDev

Velkou výhodou tohoto řešení je jednoduché spouštění a možnost navázání deploymentu na libovolné další úlohy.

Neváhejte mě kontaktovat

V případě zájmu o mé služby mě můžete kontaktovat na

pavel@pavelkovar.cz

nebo

Fyzická osoba zapsaná v Živnostenském rejstříku od 30. 7. 2014, eviduje Městský úřad Rožnov pod Radhoštěm,
Pavel Kovář, IČO: 03246078