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

17

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

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

FROM mysql

ENV MYSQL_ROOT_PASSWORD="bagabu"
ENV MYSQL_DATABASE="imhere"

ADD imhere.sql /tmp/imhere.sql

RUN "mysql -u root --password="bagabu" imhere < /tmp/imhere.sql"

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

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

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

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

Том Клино
источник

Ответы:

14

Вы должны поместить ваш скрипт инициализации в каталог, смонтированный как /docker-entrypoint-initdb.d- см. Раздел «Инициализация нового экземпляра» в документации по образу MySQL Docker .

Грег Дубицки
источник
2
Это работает для того, чтобы вызвать новый контейнер и загрузить его с моей схемой. Что является хорошим способом обойти это, но что, если я ищу способ создать свой собственный образ докера, у которого уже есть предустановленная схема?
Том Клино
На самом деле, неважно :-) Я думал, что это /docker-entrypoint-initdb.dбыло в хосте, но это на самом деле в контейнере. Я изменил ADDкоманду для копирования в этот каталог и удалил RUNкоманду. Докер успешно создал образ, и я проверил его, и он работает.
Том Клино
14

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

Вот как я это сделал, используя реальные изображения 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 init
RUN ["sed", "-i", "s/exec \"$@\"/echo \"not running $@\"/", "/usr/local/bin/docker-entrypoint.sh"]

# needed for intialization
ENV MYSQL_ROOT_PASSWORD=root

COPY 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:latest

COPY --from=builder /initialized-db /var/lib/mysql

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

Мартин Рой
источник
2
лучший ответ, который я нашел во всем Интернете, мой был для postgres, так что это было немного сложнее, но, наконец, все заработало. И это работает отлично!
snowe2010
Более старые версии mysql (5.7.9) не имеют /usr/local/bin/docker-entrypoint.sh, символьной ссылки на /entrypoint.sh, вместо этого просто есть entrypoint.sh в /. Изменение /usr/local/bin/docker-entrypoint.sh на /entrypoint.sh работает и, вероятно, должно работать и для «современных» выпусков.
Марвин
2

Кредиты @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 init
RUN ["sed", "-i", "s/exec \"$@\"/echo \"not running $@\"/", "/usr/local/bin/docker-entrypoint.sh"]

# needed for intialization
ENV MYSQL_ROOT_PASSWORD=root

COPY 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:latest

COPY --from=builder /initialized-db /var/lib/mysql

Содержание setup.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

Венкатешвара Рао
источник
-1

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

Патрик
источник
Это интересно - я использовал Ansible, но не использовал его для образов Docker. Не могли бы вы расширить свой ответ несколькими примерами, Патрик?
Грег Дубицки
У Ansible есть отличная страница документации, вы можете найти модуль Ansible по этому адресу: docs.ansible.com/ansible/docker_module.html На каждой странице в главе модуля данного руководства есть несколько примеров.
Патрик