Rubriky
Blog

Z WAMPu do Dockeru, jednoduše

Motivace

Vždy když přijímáme nového vývojáře do ExitShopu tak největší peklo je, rozjet si systém lokálně, typicky na nějakém tom WAMPu (Xampp, Neard….). Obvykle to zahrnuje tři kroky:

  1. Naklonovat si repozitář
  2. Donahrát neverzované soubory (configy a nějaká defaultní uživatelská data – obrázky atd)
  3. Naimportovat databáze

Mezitím se může pokazit asi tak sto věcí:

  1. Vývojář nebude mít požadovanou PHP extension,
  2. bude mít jinou verzi PHP než je na produkci,
  3. bude mít špatně nakonfigurované PHP
  4. (body 1-3 platí navíc zvlášť i pro každou součást vašeho stacku)
  5. nebude umět (nebo být ochoten) si nastavovat virtual hosty
  6. nebude umět (nebo být ochoten) nastavovat si lokální SSL certifikát
  7. nebude umět (nebo být ochoten) si nainstalovat další služby typu Redis, memcached, fake smtp server, …

Řešení – sjednocení vývojového prostředí

Tedy co se operačního systému a služeb týče. Vyvíjet můžete samozřejmě dál ve svých oblíbených programech. Docker už nějakou dobu běží bez problému i pod Windows takže ani ve vašem OS nebude problém.

Příklad z praxe – převední PHP a MySQL aplikace z WAMPu do Dockeru

Představte si, že máte aplikaci běžící pod nějakou konkrétní verzí PHP, například 8. K tomu budete chtít Apache a MariaDB a celé to poběží na Debianu.

Nejprve si nainstalujeme Docker Desktop.

Vezmeme zdrojáky z WAMPu a nakopírujeme si je jinam, třeba do C:\Docker\mojeappka

WAMP můžeme vypnout ale v systému si ho určitě nechte. Nemusíte hned každou aplikaci Dockerizovat a tyto dva systémy mohou v pohodě existovat vedle sebe.

Dockerfile

Je to hlavní soubor, dáme si ho do rootu aplikace, budeme jej verzovat ale na produkci jej nahrávat nebudeme :)

Rovnou sem dám příklad. Na prvním řádku definujeme, z jaké image chceme vycházet. Vybral jsem tuhle, která kombinuje Debian Buster, Apache a PHP verzi 8.0.3.

FROM php:8.0.3-apache-buster

# nakopírování apache vhosts
COPY docker-konfigurace/000-default.conf /etc/apache2/sites-available/000-default.conf

# nakopírování našich změn pro php.ini
COPY docker-konfigurace/my-php.ini /usr/local/etc/php/conf.d/my-php.ini

# update
RUN apt-get update

# doinstalujeme PHP extension
RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli

# příklad instalace programu z deb balíčku
RUN apt-get install -y wget
RUN wget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.buster_amd64.deb
RUN apt install -y ./wkhtmltox_0.12.6-1.buster_amd64.deb

# povolení apache modulů
RUN a2enmod rewrite

Následuje nakopírování virtual hostů. Příklad takového souboru níže. Všimněte si té cesty. I když jsme na Windows, tak definujeme cesty na zvoleném OS (Debianu).

<VirtualHost *:80>
    DocumentRoot "/var/www/html"
    ServerName mojeappka.test
    ServerAlias www.mojeappka.test

    <Directory "/var/www/html">
        Options Indexes FollowSymLinks MultiViews
        AllowOverride all
    </Directory>
</VirtualHost>

Následuje nakopírování změn oproti defaultnímu php.ini souboru. Může to být třeba vyšší memory limit atd.

Pak spustíme update, abychom při instalaci balíčků měli nové verze. Balíčku můžeme instalovat tak, jak jsme z Linuxu zvyklí – z repozitářů nebo z .deb balíčků. PHP extensions můžeme šikovně instalovat přes docker-php-ext-install XX.

To bychom měli Dockerfile, který definuje náš kontejner.

docker-compose.yml

Tento soubor nám dovolí nakombinovat více služeb do jednoho celku. Dáme si ho do rootu aplikace, budeme jej verzovat ale na produkci jej opět nahrávat nebudeme :)

version: '3.8'

services:
  web:
    image: php:8.0.3-apache-buster
    ports:
      - '80:80'
    volumes:
      - .:/var/www/html/
    build: .
    links:
      - db
    extra_hosts:
      - "mojeappka.test:127.0.0.1"
    hostname: mojeappka.test

  db:
    image: mariadb:10.3.23
    restart: 'always'
    ports:
      - "3306:3306"
    volumes:
      - ./docker-konfigurace/databases:/docker-entrypoint-initdb.d
    environment:
      MYSQL_ROOT_PASSWORD: heslo

  adminer:
    image: adminer
    restart: always
    ports:
      - 8080:8080

Na příkladu vidíme 3 služby. Prvním je webový server, který jsme prakticky konfigurovali výše. Nastavíme mu porty, na kterých má běžet, hostname a a volume – čili kde se má v tom Debianu připojit náš projekt.

Další službou je databáze – zvolíme image, nastavíme porty, v sekci volumes můžeme určit cestu k adresáři (docker-konfigurace/databases), kde máme strukturu DB v SQL souborech – tím se nám při prvotním zbuildování kontejneru nahraje DB. A taky root heslo k db.

Všimněte si další služby – Adminer. Bude běžet na portu 8080, čili localhost:8080. Tak jednoduché je přidávat si další služby.

Jdeme na to

Máme to nachystané. Spustíme tenhle příkaz. Stáhnou se images, provede se jejich instalace a spustí se příkazy v našem Dockerfile – instalace balíčků atd.

docker-compose build

A teď to celé spustíme:

docker-compose up

A mělo by to jet :)

  • na http://localhost/ (případně mojeappka.test, pokud si nastavíte v systému hosts file) běží web
  • na http://localhost:8080/ běží Adminer – do DB se připojíme na hostname “host.docker.internal”, uživatel “root”, heslo “heslo”

Spouštět kontejnry můžete i z GUI Docker Desktopu:

Vyplatí se to všechno?

Ano, pro větší aplikace, na kterých deláte denně, v týmu nebo která má nějaké specifičnější nároky na konfiguraci nebo služby, tak to určije ano.

Nemusíte ale hned vše dockerovat. Rychlejší je samozřejmě hodit si aplikaci do WAMPu (aktuálně používám Neard, protože se nemusí instalovat a má hezké rozhraní pro tvorbu vhostů, ssl a další vychytávky) a ona tak nějak běží ihned.

Rubriky
Blog

Jak jednoduše zautomatizovat testování webové stránky – Selenium a Webdriver

Po každé větší změně v projektu, případně rovnou při každém releasu je vhodné otestovat základní funkčnost aplikace. End-to-End testování přímo v prohlížeči je jednou z možností a je s tím podle mě sranda.

End-to-end testing is a methodology used to test whether the flow of an application is performing as designed from start to finish.

https://www.techopedia.com/definition/7035/end-to-end-test

Co budeme potřebovat?

Facebook Webdriver si stáhneme přes composer, Selenium a ChromeDriver si stáhneme klasicky a naše složka bude vypadat takto:

Píšeme test

Založíme soubor test.php, ten může vypadat nějak takto:

<?php

use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\WebDriverDimension;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\WebDriverExpectedCondition;

require_once 'vendor/autoload.php';

// config
$host = 'http://localhost:4444/wd/hub';
$options = new ChromeOptions();
$options->setExperimentalOption('prefs', ['download.default_directory' => 'c:/temp']);
$capabilities = DesiredCapabilities::chrome();
$capabilities->setCapability(ChromeOptions::CAPABILITY, $options);

// create driver and resize window
$driver = RemoteWebDriver::create($host, $capabilities, 5000); 
$driver->manage()->window()->setSize(new WebDriverDimension(1360, 768));

// start testing this URL
$driver->navigate()->to("https://www.skoula.cz/");

// click on some element
$driver->findElement(WebDriverBy::cssSelector('.menu-item-1233 a'))->click();

// check URL if we are there already
$driver->wait(5, 500)->until(
    WebDriverExpectedCondition::urlContains('projekty')
);

// is there some element?
if ($driver->findElements(WebDriverBy::className('entry-title'))) {
    echo "ok";
} else {
    echo "ko";
}

A jak probíhá testování?

  1. Nejprve si spustíme Selenium Server – stačí spustit stažený .jar soubor.
  2. Pak spustíme náš test.php – ať už v prohlížeči nebo přes konzoli.

Jak to vypadá v praxi vidíte na tomto videu. Není zrychlené :)

Celý tento mini projekt si můžete stáhnout zde.

Rubriky
Blog

Dva užitečné nástroje pro automatické vylepšení PHP kódu – ECS a Rector

Prvním z nich je Easy Coding Standard. Nainstalujete si ho klasicky přes composer (ať už do vašeho projektu nebo bokem) a jednoduše spustíte v konzoli:

vendor/bin/ecs check src --level clean-code --fix

Příklad výše spustí ECS pro adresář src, pomocí volby –level si určíme, co se má opravovat (je tam přednastavených mnoho configů) a pomocí –fix určíme, že se to má rovnou opravit, ne jen vypsat.

Dalším zajímavým nástrojem je Rector. Prezentuje se jako nástroj pro upgradování, případně pro migraci mezi frameworky ale umí i jiné věci – například odstraňovat “dead code” čili pozůstatky kódu, který se nikdy neprovede. Instalace probíhá opět přes composer a spustit ho můžeme následovně:

vendor/bin/rector process src --level dead-code

Příklad výše spustí Rector nad adresářem src a rovnou ho nechá opravovat kód. Pokud přidáme volbu –dry-run, kód se neopraví, nejprve tedy budete mít možnost vidět výsledky operace.

Pro seznam configů můžete spustit:

vendor/bin/rector levels

UPDATE: místo levels použijte sets :)