Docker na Windows efektivně

Docker je perfektní technologie, která dokáže udělat váš život příjemnější (za předpokladu, že jste vývojář, jinak asi moc ne). Její používání (nejen) na Windows však dokáže být pěkný opruz a místo nových možností máte chuť se na něj spíš vybodnout. Jak z toho ven?


Update

Momentálně existuje lepší způsob, jak používat Docker na Windows – Docker for Windows, který přináší lepší výkon a jednodušší ovládání.

Co je to vlastně ten Docker?

Řekněme že je to jakási alternativa k virtualizaci. Klasická virtualizace emuluje hardware, na kterém následní běží hostovaný systém (guest). Docker oproti tomu využívá kontejnerů, které sdílejí kernel se hostujícím systémem (hostem). To umožňuje mnohem větší výkon a není tak problém si na desktopu spustit třeba 200 různých kontejnerů zaráz. Na druhou stranu jelikož se sdílí kernel, konkrétně Linuxový, nelze Docker spustit na ledajakém systému. Na Windows (či OSX) se proto používá lehký virtuální stroj (VM) s malou linuxovou distribucí – boot2docker postavený na TinyCore linux.

Proč bych ho měl chtít?

Konec nudné přednášky, jdem si zprovoznit Docker!

(Pro vysvětlení budu používat Windows 10, na jiných verzích se můžou hlavně názvy lišit)

Instalace Toolboxu

Stáhneme a nainstalujeme Docker Toolbox – balíček obsahující Virtualbox, Docker, Docker Machine a Docker Compose (později).

Po instalaci spustíme Docker Quickstart Terminal – skript, který najdete v nabídce Start. Ten nám ve Virtualboxu vytvoří VM s nainstalovaným Dockerem. V tomto VM budou žít všechny naše kontejnery. Název machine je ve výchozím nastavení default.

Pokud skript selže, zkuste se podívat, jestli nemáte ve Windows zapnuté Hyper-V. Jestli jo, tak ho vypněte, nejsou s Virtualboxem kámoši.

Vytvořený VM má out-of-the-box nastavené sdílení složek s hostem. Konkrétně adresář C:/Users (ve VM namountovaný jako /c/Users).

První kontejner

Na stránkách Dockeru je popsané vytváření prvního kontejneru, ale to je docela nuda.

Vyzkoušíme si rovnou spustit nějaký PHP skript v kontejneru.

Všechny následující příkazy se budou odehrávat v emulátoru bashe (Git Bash, MinTTY, apod.) Vzhledem k tomu, že tyto emulátory mají na Windows spoustu chyb znemožňujících rozumnou práci přímo s Dockerem, tak budeme pro definování našich kontejnerů používat Docker Compose.

Vytvoříme si nový adresář někde ve sdílené složce – třeba C:/Users/{USER}/dev.

V něm si vytvoříme náš soubor docker-compose.yml s následujícím obsahem:

version: '2'
    
services:
    app:
        image: php:7-apache
        volumes:
            - .:/var/www/html
        ports:
            - 80:80

Co tato konfigurace říká:

Spustíme bash a provedeme příkaz:

$ eval $(docker-machine env default)

Tím nastavíme v bashi proměnné, podle kterých Docker pozná, že u všech dalších příkazů budeme vždy chtít použít náš VM s názvem default.

Teď už můžeme spustit náš kontejner:

$ docker-compose up

Zjistíme si IP našeho VM a otestujeme ji v prohlížeči:

$ docker-machine ip

Stejného výsledku bychom dosáhli i pomocí příkazu (po nastavení proměnných pomocí eval)…

$ docker run -it --name dev_app -d -v $(pwd):/var/www/html -p 80:80 php:7-apache

…což je o něco ošklivější, ale hlavně to nejspíš nebude fungovat.

Teď stačí jen přidat do adresáře nějaký PHP skript (klidně v bashi):

$ echo "<?php phpinfo();" > index.php

Po aktualizaci stránky v prohlížeči uvidíme výpis informaci o nainstalovaném PHP.

V kontejneru nám běží Apache s PHP 7. Málokdo z nás však staví aplikace sestávající z jednoho skriptu. Zkusíme něco většího. Co takhle Nette Sandbox?

Otevřeme si bash v kontejneru:

$ docker exec -it dev_app bash

Pokud příkaz vrátí chybu “cannot enable tty mode on non tty input”, napište před něj winpty.

Nainstalujeme git, Composer a stáhneme sandbox:

$ apt-get update -y && apt-get install git
$ curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
$ composer create-project nette/sandbox

Otevřeme v prohlížeči http://{VM IP}/sandbox/www a přivítá nás úvodní obrazovka sandboxu.

Možná si všimnete delší odezvy oproti sandboxu běžícímu na lokále. U mě asi čtyřnásobné. V případě složitější aplikace (Doctrine, hodně cachování, události) vám běžný request trvá až několik vteřin. Not cool. Problémem je vboxsf, filesystem pro sdílené složky ve Virtualboxu, který je zaprvé strašně pomalý a za druhé zrovna rozbitý. Co s tím?

Alternativa k vboxsf

Jako první jsem zkusil Sambu, kterou doporučuje většina windowsáků okolo Dockeru, ale ta přinesla jen mírné zvýšení rychlosti. Já chci ale rychlost minimálně srovnatelnou s lokálem! Hledal jsem, až jsem konečně objevil Unison.

Není to vyložené filesystem pro namountování adresáře do virtuálního stroje. Jedná se o nástroj pro synchronizaci souborů – něco jako rsync, ale s plně funkčním oboustraným provozem.

Jeho zprovoznění je navíc hračka. Stačí stáhnout unison na Windows a využít malý skript, který jsem si pro tuto potřebu napsal. Jdeme na to.

Pokud nám stále běží původní kontejner, tak ho zničíme pomocí

$ docker-compose kill

Naklonujeme si repozitář někde mimo složku s projektem, přesuneme se do adresáře, a spustíme skript pro synchronizaci souborů.

$ git clone git@github.com:fmasa/docker-machine-unison.git
$ cd docker-machine-unison
$ ./provision.sh

Unison zůstává běžet podobně jako watch task v Gulpu nebo Gruntu. První spuštění může trvat i několik vteřin/výjimečně minut (záleží na velikosti sdílené složky).

V základním nastavení se sdílí právě dev v domovské složce uživatele.

Zkusíme si opět vytvořit kontejner pro Nette sandbox. Na mém PC šla průměrná délka requestu u prázdného sandboxu z 350ms na 50ms, to už není špatné!

Budu rád za náměty na zlepšení či pull requesty.

Hledáte PHP vývojáře na part-time, nebo krátkodobý kontrakt v Brně, nebo remote?
Napište mi email frantisekmasa1@gmail.com

Komentáře