инициализация/загрузка базы данных MySQL из файла docker-compose

Привет всем 👋

В этой короткой статье мы рассмотрим, как запустить базу данных MySQL прямо из docker-compose.

предварительные условия

  • некоторое знакомство с Docker и Docker Compose
  • некоторое знакомство с MySQL или MariaDB

проблема

Вы оказались в ситуации, когда вам нужно запустить какой-то скрипт или даже специальный код из вашего приложения для выполнения некоторых проверок, чтобы взаимодействовать с таблицей или создать и запустить базу данных программно, если некоторые данные или схемы не присутствуют в вашей базе данных?

На мой взгляд, это проблема, поскольку:

  • ваша база данных и ваше приложение становятся тесно связанными
  • вы тратите драгоценное время на настройку вышеупомянутого.

К сожалению, и это открытое мнение, эта тесная связь стала мейнстримом благодаря большому количеству веб-фреймворков, предоставляющих мощные системы миграции данных.

решение: использовать контейнерную службу селекции

Идея заключается в том, чтобы создать контейнер, который запускается только один раз для посева базы данных и затем не перезапускается при выполнении команды docker compose up; причина, по которой мы создаем отдельный сервис вместо того, чтобы запускать команду непосредственно в основном докер-сервисе базы данных, заключается в том, что мы не хотим, чтобы скрипт посева запускался, если, скажем, мы реализовали постоянство данных между перезапусками контейнера для этого сервиса…

Давайте проиллюстрируем это!

Во-первых, давайте напишем действительно простой SQL, который создаст таблицу, если она не существует:

CREATE TABLE IF NOT EXISTS `test_table` (
  `test_field` varchar(255) DEFAULT NULL,
  `test_field2` int(11) DEFAULT 0
) ENGINE=InnoDB;
Войти в полноэкранный режим Выйти из полноэкранного режима

… теперь перейдем к нашему файлу docker-compose:

volumes:
  db-vol:

services:

  # We have 3 services: the database, the db seeder, and phpmyadmin

  db:
    image: mysql:latest
    container_name: db
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: "true"
      MYSQL_DATABASE: test_db
    restart: unless-stopped
    volumes:
      - db-vol:/var/lib/mysql
    ports:
      - "3306:3306"

  db_seeder:
    image: mysql:latest
    volumes:
      - ./db.sql:/db.sql
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: "true"
    entrypoint: [ "bash", "-c", "sleep 10 && mysql --user=root --host=db --port=3306 test_db < /db.sql && exit"] 
    depends_on:
      - db

  phpmyadmin:
      image: phpmyadmin:latest
      restart: unless-stopped
      ports:
          - 8080:80
      environment:
          # we specify that we connect to an arbitrary server with the flag below
          # "arbitrary" means you're able to specify which database server to use on login page of phpmyadmin      
          - PMA_ARBITRARY=1
      depends_on:
        - db_seeder
Войти в полноэкранный режим Выйти из полноэкранного режима

В этом файле первым сервисом является db, это наша основная база данных в стеке приложений, которая перезапускается, если не остановлена; у нее есть том db-vol, который позволит нам сохранять данные между перезапусками контейнера.

Второй сервис — db_seeder, это контейнер, в который скопирован наш посевной SQL скрипт (в разделе volumes); он явно установлен в зависимость от основного сервиса базы данных (с помощью директивы depends_on), так как мы не можем запустить SQL скрипт против базы данных, если база данных еще не существует, верно?
Когда создается контейнер сеялки, в нем запускается инструкция bash, которая говорит:

  • немного поспать (чтобы убедиться, что все SQL-соединения успели установиться)
  • подключиться к основной службе базы данных: mysql --user=root --host=db --port=3306
  • запустите sql-скрипт против указанной базы данных, нашей test_db: test_db < /db.sql
  • выйти из оболочки

Наш третий сервис — это графический интерфейс phpmyadmin, который позволяет вам легко проверить, что находится в вашей базе данных и все ли работает, как ожидалось (пользователь root с хостом db в этом примере).

Надеюсь, это поможет! До встречи!

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *