Podłączenie kontenera aplikacji do bazy danych MySQL

Czas czytania: 2 minut

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.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *