Wstęp
W poprzednim wpisie tworzyliśmy produkcyjne kontenery dla aplikacji symfony przy użyciu docker’a. Dzisiaj poznamy możliwości podłączenia kontenera PHP do bazy danych.
W tym celu użyjemy bazy danych MySQL wersji 8. Istnieje kilka sposobów podłączenia bazy danych:
- dla każdej aplikacji tworzymy osobny kontener bazy danych
- tworzymy pojedynczy kontener bazy danych (lub instalujemy bazę danych bezpośrednio na serwerze), który może być użyty w kilku aplikacjach (współdzielenie bazy danych pomiędzy aplikacjami)
- korzystamy z zewnętrznej bazy danych (np. chmurowej)
Każde z rozwiązań ma swoje wady i zalety. Celem zadania będzie stworzenie optymalnego rozwiązania, które będzie można wykorzystać na serwerze VPS.
Osobny kontener bazy danych dla każdej aplikacji
Tworząc osobny kontener bazy danych dla aplikacji, wystarczy, że rozwiniemy nasz plik docker-compose.prod.yml
.
mysql: image: mysql:8 command: --default-authentication-plugin=mysql_native_password restart: on-failure:3 environment: MYSQL_DATABASE: symfony MYSQL_USER: symfony MYSQL_PASSWORD: symfony MYSQL_ROOT_PASSWORD: root networks: - symfony volumes: - db:/var/lib/mysql volumes: logs: name: symfony_logs db: name: symfony_db
Dodajemy kontener z obrazem mysql:8
oraz tworzymy nowy volume o nazwie db
, aby przechowywać tam dane z bazy danych.
Zaletą tego rozwiązania jest to, że mamy osobny kontener dla każdej aplikacji (izolacja). W przypadku gdy chcielibyśmy uruchomić kilka aplikacji posiadających osobny kontener bazy danych, szybko możemy przepalić ilość dostępnej pamięci RAM na serwerze, co będzie wadą tego rozwiązania.
Kolejną zaletą będzie automatyczne tworzenie użytkownika i bazy danych w kontenerze za pomocą zmiennych środowiskowych (gdy wykorzystamy pojedynczy mysql będzie trzeba tworzyć ich ręcznie).
Współdzielenie bazy danych pomiędzy aplikacjami
Istnieją dwie drogi:
- instalacja skonteneryzowanej bazy danych mysql
- instalacja bazy danych mysql bezpośrednio na serwerze
Użycie kontenera
Na naszym serwerze produkcyjnym, przygotujemy osobny plik docker-compose.yml
poza katalogiem aplikacji:
version: '3.7' services: mysql: image: mysql:8 command: --default-authentication-plugin=mysql_native_password container_name: mysql restart: always environment: MYSQL_ROOT_PASSWORD: root networks: - mysql volumes: - db:/var/lib/mysql volumes: db: name: mysql_db networks: mysql: name: mysql
W kontenerze utworzymy bazę danych i użytkownika (IP 172.19.%
to adres po którym łączą się kontenery dockera):
docker exec -it mysql bash mysql -p # wpisujemy hasło zdefiniowane w kontenerze CREATE DATABASE symfony; CREATE USER 'symfony'@'172.19.%' IDENTIFIED BY 'symfony'; FLUSH PRIVILEGES; GRANT ALL PRIVILEGES ON symfony.* TO 'symfony'@'172.19.%'; FLUSH PRIVILEGES;
Następnie w pliku docker-compose.prod.yml
naszej aplikacji wystarczy dodać sieć bazy danych:
php: build: context: . target: symfony_php_prod container_name: symfony_php restart: on-failure:3 environment: APP_ENV: prod DATABASE_URL: "mysql://symfony:symfony@mysql:3306/symfony?serverVersion=8.0" mem_limit: 256M mem_reservation: 128M cpus: 0.3 networks: - symfony - mysql volumes: - logs:/app/var/log networks: symfony: name: symfony mysql: external: true
Podejście to spowoduje, że kontener php
będzie dostępny w sieci aplikacji oraz bazy danych.
Baza danych bezpośrednio na serwerze
Instrukcję jak zainstalować bazę danych na serwerze można znaleźć w wielu miejscach. Dla systemy debian będzie to np. https://computingforgeeks.com/how-to-install-mysql-8-0-on-debian/
Podłączenie zainstalowanej na serwerze bazy danych do aplikacji działających jako kontener dockera możemy zrealizować dodając następujące linie do docker-compose.prod.yml
php: build: context: . target: symfony_php_prod container_name: symfony_php restart: on-failure:3 environment: APP_ENV: prod DATABASE_URL: "mysql://symfony:symfony@host.docker.internal:3306/symfony?serverVersion=8.0" mem_limit: 256M mem_reservation: 128M cpus: 0.3 networks: - symfony volumes: - logs:/app/var/log extra_hosts: - "host.docker.internal:host-gateway"
Polecenie extra_hosts
dodaje nam hosta host.docker.internal
z IP naszego hosta do pliku /etc/hosts
, dzięki czemu możemy się połączyć z bazą danych znajdującą się na hoście. Polecenie jest dostępne dla dockera wersji +20.10.
Podsumowanie
Zaletą obu rozwiązań jest oszczędność pamięci RAM serwera.
W przypadku kontenera mysql
wszystkie aplikacje będą dostępne w sieci mysql
, co można uznać na delikatną wadę. Będziemy musieli również volume, który odpowiada za zapamiętanie stanu bazy danych.
Gotowe rozwiązanie sprawdzisz na branchu mysql https://github.com/grandmaster44/symfony-docker/tree/mysql
Co wybrać?
Posiadając wiele aplikacji na jednym serwerze VPS, bez wątpienia korzystniejszym wyborem będzie pojedynczy serwer mysql. Użycie kontenera będzie prostszym rozwiązaniem pod względem konfiguracji i uruchomienia, a zainstalowanie mysql bezpośrednio na serwerze pozwoli na pominięcie tworzenia volume i synchronizacji plików.