Привет всем 👋
В этой короткой статье мы рассмотрим, как запустить базу данных 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
в этом примере).
Надеюсь, это поможет! До встречи!