Создание контейнера docker mysql с подготовленной схемой базы данных

Я хочу создать образ docker поверх образа mysql, который уже содержит необходимую схему для моего приложения.

Я попытался добавить строки в файл Dockerfile, который импортирует мою схему в виде sql-файла. Я сделал это как таковой (мой файл Dockerfile):

FROM mysqlENV MYSQL_ROOT_PASSWORD="bagabu"ENV MYSQL_DATABASE="imhere"ADD imhere.sql /tmp/imhere.sqlRUN "mysql -u root --password="bagabu" imhere < /tmp/imhere.sql"

Насколько я понимаю, это не сработало, потому что образ mysql docker не содержит клиента mysql (рекомендации гласят: "не добавляйте вещи только потому, что их будет приятно иметь") (я ошибаюсь в этом?)

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

  1. установите клиент mysql, сделайте то, что я должен с ним сделать, затем удалите / очистите его.
  2. скопируйте двоичный файл клиента mysql в изображение, сделайте то, что я должен сделать, затем удалите его.
  3. Создайте схему на другом сервере sql и скопируйте непосредственно файл базы данных (это кажется очень запутанным и звучит для меня как зараженный пул проблем)

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

Я должен был сделать это в целях тестирования.

Вот как я это сделал, используя фактические образы MySQL / MariaDB на dockerhub и многоступенчатую сборку:

FROM mariadb:latest as builder# That file does the DB initialization but also runs mysql daemon, by removing the last line it will only initRUN ["sed", "-i", "s/exec \"$@\"/echo \"not running $@\"/", "/usr/local/bin/docker-entrypoint.sh"]# needed for intializationENV MYSQL_ROOT_PASSWORD=rootCOPY setup.sql /docker-entrypoint-initdb.d/# Need to change the datadir to something else that /var/lib/mysql because the parent docker file defines it as a volume.# https://docs.docker.com/engine/reference/builder/#volume :#       Changing the volume from within the Dockerfile: If any build steps change the data within the volume after#       it has been declared, those changes will be discarded.RUN ["/usr/local/bin/docker-entrypoint.sh", "mysqld", "--datadir", "/initialized-db", "--aria-log-dir-path", "/initialized-db"]FROM mariadb:latestCOPY --from=builder /initialized-db /var/lib/mysql

Полный рабочий пример здесь : https://github.com/lindycoder/prepopulated-mysql-container-example

Вы должны поместить свой сценарий инициализации в каталог, смонтированный как /docker-entrypoint-initdb.d - см. раздел "Инициализация нового экземпляра" в MySQL Docker image docs.

Кредиты @Martin Roy

Внесены незначительные изменения для работы с mysql...

Содержимое Dockerfile

FROM mysql:latest as builder# That file does the DB initialization but also runs mysql daemon, by removing the last line it will only initRUN ["sed", "-i", "s/exec \"$@\"/echo \"not running $@\"/", "/usr/local/bin/docker-entrypoint.sh"]# needed for intializationENV MYSQL_ROOT_PASSWORD=rootCOPY setup.sql /docker-entrypoint-initdb.d/# Need to change the datadir to something else that /var/lib/mysql because the parent docker file defines it as a volume.# https://docs.docker.com/engine/reference/builder/#volume :#       Changing the volume from within the Dockerfile: If any build steps change the data within the volume after#       it has been declared, those changes will be discarded.RUN ["/usr/local/bin/docker-entrypoint.sh", "mysqld", "--datadir", "/initialized-db"]FROM mysql:latestCOPY --from=builder /initialized-db /var/lib/mysql

Настройка содержимого.sql

CREATE DATABASE myexample;USE myexample;CREATE TABLE mytable (myfield VARCHAR(20));INSERT INTO mytable VALUES ('Hello'), ('Dolly');

Полный рабочий пример здесь : https://github.com/iamdvr/prepopulated-mysql-container-example

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

FROM mariadb:10.5.5ENV MYSQL_ROOT_PASSWORD=blablablablablablaCOPY settings/my.cnf /etc/mysql/conf.d# comment out !includedir /etc/mysql/conf.d/ to stop recursionRUN sed -i 's/!includedir \/etc\/mysql\/conf\.d\//#!includedir \/etc\/mysql\/conf\.d\//' /etc/mysql/conf.d/my.cnfCOPY db_scripts/db_setup.sql /docker-entrypoint-initdb.d/COPY db_scripts/db_data.sql.template /docker-entrypoint-initdb.d/db_template.sqlCOPY db_scripts/db_users.sql /docker-entrypoint-initdb.d/# Note the port 3306 can be exposed

Ответ @Venkateswara Rao и @Martin Roy отлично работают, если вам все равно, будут ли изменения в dockerized DB по-прежнему помещены в том. В моем случае я хотел, чтобы изображение Docker было предварительно заполнено данными, но в проекте, где у нас частые миграции баз данных. Таким образом, я хотел время от времени создавать контейнер БД, запускать миграции, а затем каким-то образом возвращать эти изменения обратно, чтобы следующий пользователь, который будет использовать образ БД, уже применял миграции. Поскольку файлы базы данных находятся в томе, они не сворачиваются в образ с docker commmit my-migrated-db-container my-new-db-image.

Мое решение состояло в том, чтобы использовать официальный MySQL (5.6 в моем случае) Dockerfile (и файл точки входа), чтобы воссоздать их работу после удаления VOLUME /var/lib/mysql линия. Из полученного изображения я затем использовал файлы Venkateswara для создания предварительно загруженного образа БД, в котором даже все будущие данные БД хранятся в самом контейнере (а не на томе).

ПРИМЕЧАНИЕ: Связанный файл Dockerfile является старым, относится к устаревшим серверам ключей GPG (т.Е. keys.openpgp.org). Вы можете заменить эти имена серверов, скажем, keyserver.ubuntu.com.

Вот мой файл docker, работающий абсолютно нормально. / sql-scripts / будет содержать ваш пользовательский sql-файл (содержащий вашу подготовленную базу данных), который выполняется после запуска контейнера. Однако вы можете захотеть взглянуть на установку тома.

FROM mysql:5.6COPY ./sql-scripts/ /docker-entrypoint-initdb.d/

Программное обеспечение для управления, такое как Ansible, может помочь вам легко автоматизировать импорт mysql без необходимости установки и переустановки клиента.Ansible имеет отличные встроенные функции для управления образами и контейнерами docker, а также базами данных mysql.

Смотрите также: Как я могу инициализировать базу данных MySQL со схемой в контейнере Docker?