Я использую MariaDB, но я думаю, что это, вероятно, применимо и к MySQL.
У меня есть проект, который работает с MariaDB, и есть некоторая начальная настройка для базы данных, которая должна быть выполнена для создания таблиц, вставки исходных данных и т.д. На основании других ответов я мог бы обычно делать ADD dump.sql/docker-entrypoint-initdb.d
, но у меня нет dump.sql
- вместо этого у меня есть скрипт python, который напрямую соединяется с MariaDB и создает таблицы и данные.
У меня есть docker-compose.yml
version: '3'
services:
db:
build: ./db
ports:
- "3306:3306"
container_name: db
environment:
- MYSQL_ROOT_PASSWORD=root
web:
build: ./web
command: node /app/src/index.js
ports:
- "3000:3000"
links:
- db
"Веб" не так важен сейчас, так как я просто хочу, чтобы db
работал.
Файл Docker, который я пытался создать для БД:
# db/Dockerfile
FROM mariadb:10.3.2
RUN apt-get update && apt-get install -y python python-pip python-dev libmariadbclient-dev
RUN pip install requests mysql-python
ADD pricing_import.py /scripts/
RUN ["/bin/sh", "-c", "python /scripts/pricing_import.py"]
Однако это не работает по разным причинам. Я дошел до точки, где pip install mysql-python
не компилируется:
_mysql.c:2005:41: error: 'MYSQL' has no member named 'reconnect'
if ( reconnect != -1 ) self->connection.reconnect = reconnect;
Я думаю, что это связано с установкой mysql-python
.
Однако, прежде чем я зашел слишком далеко, я хочу убедиться, что мой подход даже имеет смысл, поскольку я даже не думаю, что база данных будет запущена, как только я получу сценарий ./pricing_import.py
и поскольку она пытается подключиться к базы данных и запускает запросы, вероятно, это не сработает.
Поскольку я не могу заставить установку python работать в контейнере mariadb
, я также думал о создании другой записи, содержащей docker-compose
которая зависит от db
и запускает скрипт python для сборки, чтобы сделать первоначальный импорт во время docker-compose build
.
Правильны ли эти из этих подходов или есть лучший способ справиться с запуском скрипта инициализации против MariaDB?
Мы используем docker-compose
healthcheck с комбинацией makefile
и bash
для обработки сценария инициализации. Таким образом, ваш docker-compose.yml будет выглядеть примерно так:
version: '3'
services:
db:
build: ./db
ports:
- "3306:3306"
container_name: db
environment:
- MYSQL_ROOT_PASSWORD=root
healthcheck:
test: mysqlshow --defaults-extra-file=./database/my.cnf
interval: 5s
timeout: 60s
Где ./database/my.cnf
- это ./database/my.cnf
с учетными данными:
[client]
host = db
user = root
password = password
Затем вы можете использовать этот скрипт health-check.bash
для проверки работоспособности:
#!/usr/bin/env bash
DATABASE_DOCKER_CONTAINER=$1
# Check on health database server before continuing
function get_service_health {
# https://gist.github.com/mixja/1ed1314525ba4a04807303dad229f2e1
docker inspect -f '{{if .State.Running}}{{ .State.Health.Status }}{{end}}' $DATABASE_DOCKER_CONTAINER
}
until [[ $(get_service_health) != starting ]];
do echo "database: ... Waiting on database Docker Instance to Start";
sleep 5;
done;
# Instance has finished starting, will be unhealthy until database finishes startup
MYSQL_HEALTH_CHECK_ATTEMPTS=12
until [[ $(get_service_health) == healthy ]]; do
echo "database: ... Waiting on database service"
sleep 5
if [[ $MYSQL_HEALTH_CHECK_ATTEMPTS == 0 ]];
then echo $DATABASE_DOCKER_CONTAINER ' failed health check (not running or unhealthy) - ' $(get_service_mysql_health)
exit 1
fi;
MYSQL_HEALTH_CHECK_ATTEMPTS=$((MYSQL_HEALTH_CHECK_ATTEMPTS-1))
done;
echo "Database is healthy"
Наконец, вы можете использовать makefile
для соединения всех вещей. Что-то вроде того:
docker-up:
docker-compose up -d
db-health-check:
db/health-check.bash db
load-database:
docker run --rm --interactive --tty --network your_docker_network_name -v 'pwd':/application -w /application your_docker_db_image_name python /application/pricing_import.py
start: docker-up db-health-check load-database
Затем запустите приложение с make start
.
make
вместо наличияdocker-compose
загрузки базы данныхdocker-compose up
.