Vytváříme vlastní Docker image pro využití v App Service na Linuxu

Pokud jste sledovali Connect(); nebo Hovory od křivého stolu nebo čtete Azure blog, určitě víte, že Microsoft několik měsíců zpátky uvedl velmi zajímavou službu nazvanou App Service on Linux. Jelikož se dnes spousta věcí točí kolem kontejnerů (např. podpora Dockeru ve Visual Studio), nejspíš vás nepřekvapí, že celá tato služba je postavená právě na kontejnerech v Dockeru. Díky tomu si můžete do App Service on Linux nasadit vlastní Docker kontejner.

V článku budu používat zkratky ASL což je App Service on Linux a ASW což je zkratka pro App Service on Windows.

Tento článek také předpokládá, že jste se již s kontejnery a s Dockerem někdy setkali. Pokud se chcete o kontejnerech a Dockeru něco dozvědět, můžete se podívat na kurz na Microsoft Virtual Academy.

Proč je to tak zajímavé?

Jedna z otázek, kterou můžete mít je "Proč říkáš, že je to důležité, když zde máme například Azure Container Service?" Odpověď je jednoduchá a přímá: Vezměte si všechny platformní funkce z App Service on Windows (škálovatelnost, vlastní domény, continuous integration, ...) a spojte to s možností využití naprosto vlastního prostředí díky Dockeru.

Vytváříme vlastní kontejnery

V základu si můžete vystačit s předem definovanými kontejnery, které vám nabízí Microsoft (v současné době máme PHP, Node a .NET Core, všechny v různých verzích prostředí). Nicméně můžete si vytvořit kontejner úplně vlastní, abyste mohli používat specifickou verzi prostředí, modulu nebo kompletně vlastní prostředí pro běh aplikace. V tomto článku si ukážeme, jak vzít HHVM od Facebooku a vytvoříme si vlastní image, která běží na App Service on Linux.

Využíváme existující kontejnery

Můžete se ptát - proč potřebujeme vytvořit vlastní kontejner, když už máme existující HHVM image na Dockeru hubu? Odpověď je ne. Tato image je pouze definované prostředí, nic víc.

Technicky byste mohli vzít nějakou existující image a použít ji v ASL, ale nebudete si moct nakonfigrovat správně logování nebo třeba nebudete mít přístup k filesystému, kde vaše aplikace leží.

Pokud jste již někdy používali Docker, určitě víte, že můžete buď vaši aplikaci zabalit přímo do image nebo úložiště s kódem aplikace namountovat - Docker se bude chovat pouze jako kontejner s prostředím pro běh aplikace.

V ASL můžete využít oba dva typy. Můžete například vzít image Admineru a nasadit ji přímo do ASL a vše bude fungovat bez jakékoliv nutné změny. Pak ale nebudete mít možnost přistupovat k souborům v kontejneru, ani pomocí FTP.

Úložiště v kontejnerech

Jak jsem již zmíil výše, aplikaci buď můžete zabalit do kontejneru, což má následně velmi podobný efekt jako použití App Service Local Cache, když používáte ASW. V tomto případě budete nejspíš využívat nějaký nástroj pro continuous integration jako VSTS, který vám automaticky sestaví a následně nasadí váš kontejner (pamatujte, že bez napojení na úložiště nebude zápis do filesystému persistentní).

Každopádně v našem případě chceme využít klasický filesystém, který je dostupný v App Service, díky kterému můžeme přistupovat k datům třeba pomocí FTP. Když se nasadí kontejner, tak ASL namountuje ekvivalent cesty D:\home na ASW do  /home v ASL (pomocí volume mount v Dockeru). Následně je na vašem kontejneru, aby si namapoval tyto cesty nebo je využíval v konfiguraci služeb. Abychom pochopili, jak toto funguje, podíváme se na Dockerfile z oficiální image, kterou používá PHP7 kontejner od Microsoftu na ASL.

Nejdůležitější častí jsou tyto řádky:

 && ln -s /home/site/wwwroot /var/www/html \
&& ln -s /home/LogFiles /var/log/apache2

Tyto dva řádky vytvářejí symbolic link mezi  /home/site/wwwroot a defaultní složkou pro Apache  /var/www/html. Namísto symbolických odkazů byste mohli tyto cesty nastavit přímo v apache2.conf souboru pro daný virtual host.

Vytváříme vlastní Dockerfile

Nyní již víme, jak funguje úložiště v ASL, takže si můžeme vytvořit vlastní Dockerfile. Jako výchozí použijeme jednu z defaultního HHVM imagí, která používá Proxygen jako webový server.

Poznámka stranou: Proxygen nikdy nebude vystrčený ven do Internetu, před hosty s kontejnery je loadbalancer, stejně jako v ASW, které také například řeší SSL terminaci.

Jak bylo již zmíněno v části o úložišti, jediné co musíme udělat je namapovat cesty ve filesystému správně, ale narozdíl od oficiální image, kde používají symbolické odkazy, budeme směrovat cesty přímo na namapované úložiště. To znamená, že nemusíme měnit samotný Dockerfile, ale pouze server.ini, což je soubor, který nese konfiguraci webového serveru. Jakmile přidáte správné cesty do konfigurace a nastavíte soubor s logy, vaše server.ini by mělo vypadat asi následnovně:

 ; php options
 
pid = /var/run/hhvm/pid
 
; hhvm specific 
 
hhvm.server.port = 80
hhvm.server.type = proxygen 
hhvm.server.default_document = index.php
hhvm.server.error_document404 = index.php
hhvm.repo.central.path = /var/run/hhvm/hhvm.hhbc
hhvm.server.source_root = /home/site/wwwroot
 
; default log location is stdout/err, which is good for docker
hhvm.log.use_log_file = true
hhvm.log.file = /home/LogFiles/hhvm.log

Celou dokumentaci k obsahu INI naleznete zde, pokud potřebujete udělat nějaké další změny.

Vytvoření a publikace kontejneru

Jediné, co nyní musíme udělat je sestavit náš kontejner a vypublikovat ho do našeho repozitáře - budeme používat Docker hub. Alternativně byste mohli využít třeba Azure Container Registry. Celý proces je velmi jednoduchý, v první fázi je potřeba přihlásit se do Docker hubu:

 docker login

A následně pak ve složce, kde se nachází váš Dockerfileserver.ini musíte spustit příkaz pro sestavení kontejneru:

 docker build -t "thenetworg/hhvm" .

Což stáhne všechny závislosti a sestaví image, který následně vypublikujeme do Docker hubu:

 docker push thenetworg/hhvm

Následně by se vám tato image měla zobrazet ve vašem profilu na Docker hubu.

Repositář s celým projektem naleznete na GitHubu, nebo ji můžete přímo nasadit z Docker hubu.

Abyste mohli vytvořit a vypublikovat vlastní kontejner, musíte mít nainstalovaný Docker - návod najdete zde. Pro tuto ukázku jsem využíval Docker na Windows. Více informací o příkazech, parametrech atd. najdete v oficiální dokumentaci.

Tento proces můžete kompletně automatizovat a nemusíte mít ani nainstalovaný Docker na vašem počítači - stačí nastavit automatické buildy na Docker hubu.

Používáme vlastní image na App Service na Linuxu

Nyní, když je image vypublikovaná, můžeme jít a vytvořit náš web s naší imagí!

Proces je velmi jednoduchý - v Azure portále stačí vytvořit nový prostředek - Web App on Linux a specifikovat název image, kteoru jste vypublikovali do Docker hubu:

appsvc-hhvm2

Po krátkém čekání můžete na FTP vytvořit soubor index.php (nebo ho vypublikovat skrze Git) a jednoduše do něj napsat  <?php phpinfo(); ?> díky kterému uvidíte, že vám na ASL běží HHVM!

appsvc-hhvm

Životní cyklus

Co se týká životního cyklu samotného kontejneru - kdykoliv potřebujete aktualizovat image (pokud vždy používáte latest verzi), tak jediné, co musíte udělat je, restartovat web, aby se načetla nová verze image. V případě, že potřebujete změnit image jako takovou nebo její verzi, můžete jít do záložky Docker a následně také provést restart webu.

Logování

Logování probíhá na dvou úrovních - logy o samotném kontejneru (jeho start, vnitřní dění, errory atd.) naleznete ve složce  /home/LogFiles/docker/ a můžete k nim přistupovat skrze FTP nebo Kudu. Díky tomu můžete dohledat chybové hlášky, které se mohly vyskytnout např. při startu kontejneru.

Dále je pak dobré donutit samotné prostředí, které provozujete v kontejneru, aby vám centrálně zapisovalo logy alespoň do filesystému tak, abyste měli přístup i k aplikačním logům, které se také občas mohou hodit.

Shrnutí

Osobně si myslím, že App Service na Linuxu nabízí velkou flexibilitu z hlediska volby naprosto vlastního prostředí v kombinaci se službami a funkcemi, na které jste zvyklí z platformního prostředí ať už se jedná třeba o škálování nebo další služby. Poslední, ale neméně důležitou věcí je to, že provozování vaší aplikaci v Linuxovém prostředí může řešit třeba i to, že některé Node.js nativní moduly (primárně psané pro Linux) nefungovaly nebo je nebylo možné zkompilovat pro App Service na Windows.