Nasza strona używa cookies. Korzystając ze strony, wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki. Rozumiem

Aplikacja Symfony w Dockerze

Gerardo Fernández Senior Developer
Poznaj kroki, które należy wykonać, aby zdokeryzować projekt w Symfony, używając Nginx, PHP-FPM oraz MySQL.
Aplikacja Symfony w Dockerze

Każdy, kto pracował ze złożonymi projektami, musiał też słyszeć o Dockerze. W skrócie, narzędzie to pozwala ujednolicić oprogramowanie używane w każdym z wielu projektów tak, aby działało w taki sam sposób, niezależnie od maszyny hosta.  

Docker zapewnia warstwę abstrakcji, którą nazywamy kontenerami. Kontenery upraszczają deployment oraz wykonanie naszych aplikacji. Dzięki nim możemy zapomnieć o jednym z najczęściej powtarzających się problemów: “U mnie działa”.

Ponieważ w kontenerach pakowane są zależności naszej aplikacji, unikamy potrzeby instalowania ich za każdym razem, gdy zmieniamy nasze stanowisko pracy. W tym artykule nauczymy się integrować Dockera z Symfony tak, aby można go było odpalić na każdym komputerze, czy serwerze. Wystarczy nam tutaj Docker zainstalowany tam, gdzie chcemy uruchomić nasz projekt. Jeżeli nie znasz jeszcze dobrze tego narzędzia, to polecam tę stronę

Przejdźmy do konkretów.


Struktura folderów  

Na początku ustalimy strukturę naszego projektu. Ponieważ używamy Dockera, będzie ona wyglądała następująco:

  • w folderze build będziemy mieć pliki, których używamy do konfiguracji każdego z kontenerów Dockera naszej aplikacji. 
  • database naszego projektu będzie w folderze mysql
  • w folderze symfony będziemy mieli aplikację, którą napisze przy użyciu naszego frameworku PHP
  • plik docker-compose.yml będzie tam, gdzie konfiguracja 3 kontenerów naszej aplikacji: ten od Nginx, ten od PHP i ten od MySQL.


Docker Compose pozwala nam zdefiniować plik z listą wszystkich kontenerów, z której będzie się składać aplikacji i później je odpalić. Konfiguracji tej dokonujemy w pliku YAML w katalogu głównym projektu.

Jeśli chcesz przeczytać więcej, sugeruję zapoznać się z oficjalną dokumentacją Dockera.


Konfiguracja kontenera Nginx 

Pierwszą rzeczą, jakiej dokonamy, jest konfiguracja kontenera, w którym znaduje się serwer Nginx. Aby to zrobić, otwieramy docker-compose.yml i dodajemy:

W czwartej linii kodu zdefiniujemy kontener Nginx:

  • dockerfile wskazuje plik konfiguracyjny, który zostanie użyty do zbudowania kontenera, który utworzymy w następnej kolejności
  • volumes stanowi o tym, że nasz lokalny folder o nazwie symfony będzie połączony z folderem /var/www/symfony w kontenerze
  • ports wykonuje mapowanie między portem 80 kontenera a portem 8001, z którego będziemy korzystać, aby uzyskać dostęp przez przeglądarkę
  • networks ustawia sieć dla całego projektu tak, aby wszystkie kontenery mogły się ze sobą komunikować


Następnie utworzymy plik Dockerfile-nginx, również w katalogu głównym naszego projektu. z następującą zawartością:

W pierwszej linii kodu zdefiniujemy obraz Nginx, którego chcemy użyć, używając dyrektywy FROM.

Dalej użyjemy metody COPY, aby skopiować zawartość pliku default.conf naszego projektu (z domyślną konfiguracją serwera, której użyje Nginx), który znajduje się w folderze /etc/nginx/conf.d kontenera.

Plik default.conf zostanie umieszczony w folderze /build/nginx i będzie wyglądał następująco:

Jak widać, w trzeciej linii mamy konfigurację root która wskazuje na folder public naszego projektu.

Ważne: Pamiętaj, że w projekcie Symfony serwer musi wskazywać nie na katalog główny projektu, ale na jego folder public.

Mając to wszystko, możemy już przetestować nasz pierwszy kontener, wykonując następujące polecenie z katalogu głównego projektu:

docker-compose up -d --build


Kod ten zbuduje jedyny kontener, jaki mamy.


Konfiguracja kontenera dla PHP

Następnym krokiem będzie stworzenie kontenera, w którym będzie działać usługa PHP FPM, dla której dodamy do naszego pliku docker-compose.yml:

Jak widać, konfiguracja jest podobna do tej, której używamy dla Nginx, z wyjątkiem następujących szczegółów:

  • W environment możemy zadeklarować zmienne środowiskowe, które chcemy, aby nasz projekt Symfony odczytał i załadował później
  • networks również składa się z jednego elementu symfony, który pozwala na komunikację tego kontenera i Nginx.
  • volumes mają taką samą wartość jak kontener Nginx, więc folder symfony naszego projektu jest połączony z folderem /var/www/symfony kontenera.


Jeśli chodzi o plik Dockerfile-php, będzie on wyglądał następująco:

Za pomocą polecenia docker-php-ext-install możemy zainstalować wszystkie potrzebne nam rozszerzenia PHP. W naszym przypadku używam tylko zip, intl i tych związanych z MySQL. Pełną listę możesz zobaczyć tutaj.

Ponownie możesz sprawdzić, czy wszystko poszło poprawnie, używając następującego polecenia:

docker-compose up -d --build


Teraz zobaczymy, jak wdrażane są dwa kontenery, Nginx i nowy PHP.


Konfiguracja kontenera dla MySQL

Kontener dla MySQL można skonfigurować, dodając do naszego pliku docker-compose.yml następujące polecenie:

W tym przypadku nie potrzebujemy pliku dockerfile, ponieważ cała konfiguracja wymagana przez nasz kontener dla MySQL może być określona w pliku YAML. Jest jednak kilka szczegółów do omówienia.

Wtyczka uwierzytelniająca

W 29 linii kodu dodałem konfigurację, która pozwala nam ustalić, która wtyczka uwierzytelniająca będzie używana podczas łączenia się z MySQL. Zrobiłem to, ponieważ do wersji PHP 7.4 nie było zgodności z wtyczką MySQL do uwierzytelniania użytkowników, co powoduje następujący błąd:

PDO::__construct(): The server requested authentication method unknown to the client [caching_sha2_password] (źródło)

Użytkownicy baz danych

W linii 31 ustawiłem hasło użytkownika root, abyśmy mogli go następnie użyć do uwierzytelnienia w Doctrine.

W przypadku, gdy chcielibyśmy wygenerować bazę danych w momencie tworzenia kontenera wraz z użytkownikiem posiadającym wszystkie uprawnienia, możemy wybrać następującą konfigurację:

Zależności między kontenerami

W linii 25 dodałem zależność od kontenera MySQL do kontenera PHP, aby były one uruchamiane w odpowiedniej kolejności.

Deploy trzech kontenerów

Po zakończeniu konfigurowania kontenera MySQL będziemy mieli wszystko gotowe, więc wykonamy polecenie zbudowania i zdeploy’owania trzech kontenerów:

docker-compose up -d --build


Jeśli wszystko poszło dobrze, zapewne otrzymasz wynik podobny do następującego:

symfony-docker_nginx_1 is up-to-date

symfony-docker_php_1 is up-to-date

Creating symfony-docker_mysql_1 ... done


Instalacja Symfony

Ponieważ od teraz będziemy pracować z naszymi kontenerami, instalacja Symfony będzie się odbywać w nich, a nie w naszym systemie operacyjnym.

Dlatego pierwszą rzeczą, którą będziemy musieli zrobić, jest udzielenie dostępu do naszego kontenera, w którym znajduje się PHP (pamiętaj, aby go pobrać) za pomocą polecenia:

docker exec -it  symfony-docker_php_1 bash


gdzie symfony-docker_php_1 to nazwa, którą polecenie docker-compose up zwróciło po zakończeniu uruchamiania kontenerów.

Teraz w kontenerze możemy zainstalować Symfony, tak jak podpowiada dokumentacja:

curl -sS https://get.symfony.com/cli/installer | bash

mv /root/.symfony/bin/symfony /usr/local/bin/symfony

symfony new symfony --dir=/var/www/symfony


Ważne: Możliwe, że przy tworzeniu projektu wystąpi następujący błąd:

*** Please tell me who you are.

Run

git config --global user.email "you@example.com"

git config --global user.name "Your Name"

to set your account's default identity


Dodanie żądanej konfiguracji Git rozwiąże ten problem.

Po zainstalowaniu Symfony możemy sprawdzić, czy wszystko zadziałało poprawnie, uzyskując dostęp do localhost: 8001 (to port, który mapujemy w Nginx w pliku docker-compose.yml), który pokaże nam stronę powitalną Symfony:

Jeśli teraz chcemy używać Doctrine do pracy z bazą danych, wystarczy zainstalować odpowiedni pakiet za pomocą composer / flex (zawsze z naszego kontenera):

composer require symfony/orm-pack
composer require --dev symfony/maker-bundle


Dodaj zmienną środowiskową DATABASE_URL do konfiguracji kontenera PHP:

DATABASE_URL: mysql://symfony_user:symfony_password@mysql:3306/symfony_db?serverVersion=5.7


Hostem bazy danych jest nazwa naszego kontenera (mysql:3306), a nie adres IP 127.0.0.1. Oznacza to, że jeśli np. nasz kontener ma nazwę database w naszym pliku docker-compose.yml, zmienna środowiskowa służąca do połączenia z tą bazą danych miałaby wartość:

DATABASE_URL: mysql://symfony_user:symfony_password@database:3306/symfony_db?serverVersion=5.7


Następnie zrestartujemy kontener, aby nanieść tę zmianę w zmiennych środowiskowych PHP:

docker-compose up -d php


Teraz możemy spokojnie pracować z naszą bazą danych. Np. w naszym kontenerze PHP możemy uruchomić polecenie:

bin/console doctrine:database:create


jeśli chcemy sprawdzić, czy projekt poprawnie łączy się z bazą danych, którą zdefiniowaliśmy.


Repozytorium

Jeśli chcesz uzyskać dostęp do pełnego kodu, znajdziesz go tutaj.


Podsumowanie

Po zdokeryzowaniu projektu możemy pracować z nim na dowolnej maszynie, nie martwiąc się o zależności czy używany system operacyjny.

To bardzo pomocne dla średnich i dużych projektów, w które zaangażowanych jest większa liczba programistów, ponieważ wszyscy będą pracować na tych samych wersjach. To zaś zapobiegnie błędom korzystania z różnych wersji w bibliotekach, których potrzebujemy.

Dodatkowo wystarczy zainstalować Dockera na maszynie, na której chcemy pracować, aby móc dalej rozwijać projekt bez konieczności instalowania po kolei niezbędnych bibliotek.



Oryginał tekstu w języku angielskim przeczytasz tutaj.

Rozpocznij dyskusję

Lubisz dzielić się wiedzą i chcesz zostać autorem?

Podziel się wiedzą z 160 tysiącami naszych czytelników

Dowiedz się więcej