Zamarzyłem sobie, żeby mieć serwer z Dockerem gdzieś tam (czyli nie na moim laptopie) i móc wygodnie na nim pracować poprzez integrację z PHPStorm. Przedstawiam zatem mój proof of concept takiej konfiguracji.
Serwer gdzieś tam
Na potrzeby testu wykupiłem sobie VPS w Znanej Firmie Hostingowej za całe 15 zł. 😉 Na serwerze postawiłem Ubuntu 16.04.
Dockeryzacja
Docker posiada narzędzie docker-machine, które służy do niczego innego, jak dockeryzowania (instalacji Dockera) i zarządzania hostami z Dockerem.
Nie będę opisywał tutaj szczegółów instalacji Dockera na moim serwerze, gdyż skorzystałem ze świetnego opisu na tym blogu. W skrócie:
- Ustawiłem logowania via SSH z mojego Maca na serwer tylko przy użyciu klucza.
- Za pomocą komendy podobnej do poniższej, z poziomu mojego laptopa, dokonałem dockeryzacji zdalnego hosta:
1docker-machine create -d generic --generic-ip-address 192.168.100.2 --generic-ssh-key $HOME/.ssh/id_rsa --generic-ssh-user dockeradmin --generic-ssh-port 22 machine_name - Po ustawieniu stosownych zmiennych środowiskowych (po użyciu komendy z punktu 2 jest pokazane jak ustawić te zmienne) Docker widział mój zdalny serwer, tak jak moją dotychczasową, lokalną instancję Dockera. Zatem np. odpalając docker-compose, tak naprawdę uruchamiałem je na zdalnym hoście.
Testowy projekt
Struktura plików testowego projektu wygląda następująco:
Docker
Podkatalog „docker” kryje konfigurację kontenera na którym uruchamiana jest testowa aplikacja.
Zawartość pliku „Docker-web1”:
1 2 3 4 5 6 7 8 9 |
FROM php:7.1.0RC4-apache RUN apt-get update && apt-get -y install git unzip; \ curl -S https://getcomposer.org/installer | php && \ mv composer.phar /usr/local/bin/composer; \ docker-php-ext-install -j$(nproc) bcmath; \ pecl install xdebug && echo "zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20160303/xdebug.so" > /usr/local/etc/php/php.ini \ && echo "xdebug.remote_enable=on" >> /usr/local/etc/php/php.ini \ && echo "xdebug.remote_connect_back=on" >> /usr/local/etc/php/php.ini \ && echo "xdebug.remote_log=/var/log/xdebug.log" >> /usr/local/etc/php/php.ini |
Są dwa pliki do docker-compose. Podstawowy („docker-compose.yml”):
1 2 3 4 5 6 7 8 9 10 11 |
version: '2' services: web1: build: context: . dockerfile: Dockerfile-web1 volumes: - "../src:/var/www/html" ports: - "32001:80" |
oraz ustwienia własne, które dostosowują montowaną scieżkę („docker-compose.dev.yml”):
1 2 3 4 5 6 7 8 |
version: '2' services: web1: volumes: - "/home/dockeradmin/bamboo_test/src:/var/www/html" ports: - "32001:80" |
Aplikacja
Aplikacja jest mocno testowa i w zasadzie ma tylko pokazać działanie PHPUnit i XDebuga.
Zwartość „src/web/index.php”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php require_once __DIR__.'/../vendor/autoload.php'; require_once __DIR__.'/../autoload.php'; $app = new Silex\Application(); $app->get('/hello/{name}', function ($name) use ($app) { $message = new \Message\Message(); return 'Hello '.$app->escape($name); }); $app->run(); |
Zawartość „src/tests/Message/MessageTest.php”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?php /** * Created by PhpStorm. * Date: 16.11.2016 * Time: 00:30 */ class MessageTest extends PHPUnit_Framework_TestCase { public function testNotEmpty() { $message = new Message\Message(); $this->assertTrue($message->show('rafal')); } public function testFailNotEmpty() { $message = new Message\Message(); $this->assertFalse($message->show('')); } } |
Uruchomienie kontenera
Przegrywamy pliki projektu na serwer zdalny – do katalogu użytkownika za pomocą, którego dokeryzowaliśmy hosta.
Następnie z poziomu lokalnego komputera upewniamy się, że docker-machine jest przełączona na zdalnego hosta:
1 |
docker-machine ls |
1 2 3 |
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS raph * generic Running tcp://193.70.85.2:2376 v1.12.3 |
Następnie można uruchomić kontener za pomocą docker-compose z lokalnego komputera:
1 |
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up web1 |
Nie zawarłem w „Dockefile-web1” instalacji zależności z Composera na kontenerze, więc należy to zrobić (np. używając dokcerowego exec).
Po wszystkim, na porcie 32001, mamy działająca aplikację.
XDebug
Właściwie integracja PHPStorm z XDebug nie różni się niczym od serwera niedokerowego. Należy tylko pamiętać, żeby nasłuchiwać na porcie wskazanym w konfiguracji PHPStorm:
Reszta postępowania jest opisana w tutorialu JetBrains.
PHPUnit
Konfigurujemy PHPUnit ze zdalnym interpreterem w zdalnym kontenerze, dodając nowy interpereter („+”):
Klikamy na „…” w celu dodania interpretera, następnie „+” i „Remote”, po czym mamy takie okno:
następnie „New…”. Po czym zaznaczamy „Import credentials form Docker Machine” i klikamy „Detect” – w ten sposób nasz zdalny kontener zostanie wykryty:
Po zatwierdzeniu mamy zdalny interpereter:
Potwierdzamy „OK” i wybieramy go z listy:
i kończymy konfigurację w oknie PHPUnit, uzupełniając najpierw ścieżki z pola „Docker container” na te na serwerze zdalnym:
Plik „phpunit.xml” zawiera konfigurację PHPUnit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.5/phpunit.xsd" verbose="true"> <filter> <blacklist> <directory>vendor</directory> <directory>tests</directory> </blacklist> <whitelist> <directory>web</directory> <directory>libs</directory> </whitelist> </filter> </phpunit> |
„autoloader.php” posłuży do załadowania klas potrzebnych PHPUnit:
1 2 3 4 5 6 7 8 9 10 11 |
<?php spl_autoload_register( function($class) { $cn = str_replace('\\', '/', $class); if (!file_exists(__DIR__ . '/libs/' . $cn . '.php')) { return; } require_once __DIR__ . '/libs/' . $cn . '.php'; } ); |
Potwierdzamy i przechodzimy do głównego okna PHPStorm, gdzie wybieramy z górnego prawego rogu:
klikamy „+” i wybieramy „PHPUnit”. Dodajemy nazwę i wybieramy, żeby zakres testu był ładowany z konfiga:
po zatwierdzeniu, wybieramy w prawym górnym rogu nasze testy i odpalamy je:
na dole widzimy wyniki:
🙂
Podusmowanie
Przedstawiłem prosty „proof of concept” jak można użyć Dockera na zdalnym hoście, integrując się przy okazji z popularnymi IDE, jakim jest PHPStorm.