Symfony na dockerze dla Maca – optymalizacja

S

Prawdopodobnie zauważyłeś także, że korzystanie z Symfony opartego o Dockera na Macu jest cholernie wolne. Rzekłbym nawet, że niemożliwe. Niezależnie od tego, jak szybki jest Twój Mac. Ten artykuł pokaże Ci kilka sposobów na przyspieszenie środowiska.

Wstęp

Docker zyskuje co raz większe grono poparcia jeśli chodzi o stawianie środowiska developerskiego. Jak zapewnie wiesz, docker daje nam wiele korzyści, które ułatwiają pracę programistom – między innymi:

  • Identycznie środowisko developerskie i produkcyjne u każdego programisty
  • Łatwość w użyciu (dostawienie jakiejkolwiek usługi zajmuje dosłownie kilka linijek konfiguracji)
  • Zdecydowanie większa wydajność w porównaniu do VM, przynajmniej na Linuksie – tak właśnie jest w tym artykule

Na początek utwórzmy sobie prosty projekt, który pokaże problem. Jeśli już takowy posiadasz, pomiń ten krok.

Demo

Ten przykładowy projekt zawierać będzie wygenerowany projekt Symfony oraz podstawową konfigurację dockera.

Symfony project

W katalogu symfony-docker-test uruchom:

Do tego potrzebujesz polecenia symfony w swoim lokalnym środowisku, opisane tutaj.

Konfiguracja kontenerów

Edytuj docker-compose.yml zgodnie z poniższym:

Budowanie kontenera PHP

Dodaj plik Dockerfile do katalogu docker/php:

Oraz konfigurację PHP do pliku docker/php/php.ini:

Utworzenie wirtualnego hosta dla nginx

Edytuj plik docker/nginx/app.conf:

Uruchom projekt

Wszystko gotowe, czas uruchomić środowisko.

Twoja aplikacja powinna być widoczna pod adresem: http://localhost:8080/app_dev.php, powinieneś zobaczyć coś podobnego

Słaba wydajność symfony na dockerze mac

Wszystko fajnie… poza jednym: aplikacja jest straszne wolna 😩

Uruchom podstawowy benchmark w środowisku produkcyjnym i developerskim (częściej będziesz korzystał z tego drugiego):

Wyniki?

  • prod: 17 sekund
  • dev: 129 sekund!!!

Rozwiązanie #1: Wyniesienie vendorów i cache

Po kilku testach (brane stąd: https://github.com/michaelperrin/docker-symfony-test), okazało się, że wąskim gardłem jest współdzielony katalog vendor, który zawiera bardzo dużo plików.

Jedynym skutecznym rozwiązaniem jest wyniesienie vendorów w miejsce, które widzi tylko kontener, a nie host.

By to zrobić, edytuj plik composer.json w katalogu app i dodaj parametr config-dir w sekcji config:

Edytuj app/autoload.php w katalogu app i zmień linijkę:

na:

Dodaj folder /app-vendor do wolumenów kontenera php w docker-compose.yml:

Upewnij się, że cache Symfony został wyczyszczony i zainstaluj zależności composera raz jeszcze:

Wyniki po tym zabiegu:

  • Prod: 2.8 sekundy
  • Dev: 16 sekund

Zobaczmy czy osiągniemy lepsze wyniki bez udostępniania katalogu cache. W pliku AppKernel.php edytuj metodę getCacheDir

Wyniki:

  • Prod: 1.2 sekundy
  • Dev: 5 sekund

Nie jest źle ale uważaj! Vendory są teraz w kontenerze, nie są widocznie na hoście. Nie będziesz w stanie debugować, podpowiedzi w IDE nie będą dostępne. Moja rada? Pierw zainstaluj zależności w standardowy sposób, następnie zmień composer.json by zainstalować je do kontenera. To rozwiązanie nie jest złe, jeśli Twoje zależności nie zmieniają się zbyt często.

Rozwiązanie #2: Docker sync

Docker sync (http://docker-sync.io/) to narzędzie korzystające z rsynca do synchronizacji volumenów między hostem a kontenerem.

Zainstaluj docker-sync:

Dodaj docker-sync.yml do głównego katalogu projektu

Skopiuj docker-compose.yml do docker-compose-dev.yml i dodaj poniższe linijki na sam koniec:

Dodaj nazwę do wolumenu katalogu app, zmieniając:

na:

Dodaj Makefile do głównego katalogu projektu, pozwoli Ci to na łatwe uruchamianie i zatrzymywanie środowiska:

Od teraz możesz startować środowisko poprzez:

To polecenie uruchomi kontenery oraz docker-synca (za pierwszym razem, wszędzie odpowiadaj na tak)

Wyniki są imponujące, ze 129 sekund zeszliśmy do 1!

  • Prod: 0.6 sekundy
  • Dev: 1.2 sekundy

Udało się! Niestety, czasem występują problemy z synchronizacją, a pliki nie są synchronizowane z hostem do kontenera, a także z niektórymi prawami użytkownika w niektórych plikach (chmod 777 do ręcznej naprawy).

Rozwiązanie #3: Cache Dockera

Zespół Dockera jest świadom słabej wydajności Dockera dla Maców. Ostatnia beta Dockera pozwala montować wolumeny w nowy sposób. Jeśli masz pobraną wersję beta, po prostu edytuj docker-compose.yml  dodając opcję :cached

 

Wyniki?

  • Prod: 5.1 sekund
  • Dev: 15.7 sekund

Nie jest źle, aczkolwiek nie tak skutecznie jak pozostałe rozwiązania. Nie jestem w chwili obecnej w stanie powiedzieć jakie są wady tego rozwiązania – ciągle z nim eksperymentuję.

Podsumowanie

Dobra wiadomość! Docker na Macu może pociągnąć projekt Symfony. Rozwiązanie nie jest idealne ale dobre chociaż tyle. W poniższej tabelce zebrałem wszystkie wyniki rozwiązań. Wybierz te, które najbardziej Ci odpowiada.

Dev benchmarkProd benchmark
Domyślnie129 sekund17 sekund
rozwiązanie #1:5 sekund1.2 sekundy
rozwiązanie #2:1.2 sekundy0.6 sekundy
rozwiązanie #3:15.7 sekund5.1 sekund

 

O autorze

Filip Nowacki

Swoją przygodę z IT rozpoczął mając 13 lat, kiedy to stworzył swoją pierwszą stronę internetową. Obecnie pracuje jako backend & mobile developer, rozwijając kilka ogólnopolskich produktów o zasięgu blisko 15 milionów użytkowników. Prywatnie maniak optymalizacji, testów A/B, motoryzacji i architektury aplikacji.

Dodaj komentarz

Your sidebar area is currently empty. Hurry up and add some widgets.