Настройка MySQL и импорт дампа в Dockerfile
Я пытаюсь настроить Dockerfile для моего проекта LAMP, но у меня есть несколько проблем при запуске MySQL. У меня есть следующие строки в моем файле Docker:
VOLUME ["/etc/mysql", "/var/lib/mysql"]
ADD dump.sql /tmp/dump.sql
RUN /usr/bin/mysqld_safe & sleep 5s
RUN mysql -u root -e "CREATE DATABASE mydb"
RUN mysql -u root mydb < /tmp/dump.sql
Но я продолжаю получать эту ошибку:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111)
Любые идеи о том, как настроить создание базы данных и импорт дампа во время сборки Dockerfile?
Ответы
Ответ 1
Каждая инструкция RUN
в Dockerfile
выполняется на другом уровне (как описано в документации RUN
).
В Dockerfile
у вас есть три команды RUN
. Проблема в том, что сервер MySQL запускается только в первом. В остальном MySQL не работает, поэтому вы получаете сообщение об ошибке с клиентом mysql
.
Для решения этой проблемы у вас есть 2 решения.
Решение 1: используйте однострочный RUN
RUN /bin/bash -c "/usr/bin/mysqld_safe --skip-grant-tables &" && \
sleep 5 && \
mysql -u root -e "CREATE DATABASE mydb" && \
mysql -u root mydb < /tmp/dump.sql
Решение 2: используйте script
Создайте исполняемый файл script init_db.sh
:
#!/bin/bash
/usr/bin/mysqld_safe --skip-grant-tables &
sleep 5
mysql -u root -e "CREATE DATABASE mydb"
mysql -u root mydb < /tmp/dump.sql
Добавьте эти строки в свой Dockerfile
:
ADD init_db.sh /tmp/init_db.sh
RUN /tmp/init_db.sh
Ответ 2
Последняя версия официального образа docker mysql позволяет импортировать данные при запуске. Вот мой docker-compose.yml
data:
build: docker/data/.
mysql:
image: mysql
ports:
- "3307:3306"
environment:
MYSQL_ROOT_PASSWORD: 1234
volumes:
- ./docker/data:/docker-entrypoint-initdb.d
volumes_from:
- data
Здесь у меня есть data-dump.sql в docker/data
, который относится к папке, с которой работает docker-compose. Я монтирую этот файл sql в этот каталог /docker-entrypoint-initdb.d
на контейнере.
Если вам интересно посмотреть, как это работает, посмотрите на docker-entrypoint.sh
в GitHub. Они добавили этот блок, чтобы импортировать данные
echo
for f in /docker-entrypoint-initdb.d/*; do
case "$f" in
*.sh) echo "$0: running $f"; . "$f" ;;
*.sql) echo "$0: running $f"; "${mysql[@]}" < "$f" && echo ;;
*) echo "$0: ignoring $f" ;;
esac
echo
done
Дополнительное примечание: если вы хотите, чтобы данные сохранялись даже после остановки и удаления контейнера mysql, вам необходимо иметь отдельный контейнер данных, как вы видите в файле docker-compose.yml. Содержимое файла Dockerfile контейнера данных очень просто.
FROM n3ziniuka5/ubuntu-oracle-jdk:14.04-JDK8
VOLUME /var/lib/mysql
CMD ["true"]
Контейнер данных даже не должен находиться в состоянии начала для сохранения.
Ответ 3
Что я сделал, так это загрузить мой sql-дамп в папку "db-dump" и установить его:
mysql:
image: mysql:5.6
environment:
MYSQL_ROOT_PASSWORD: pass
ports:
- 3306:3306
volumes:
- ./db-dump:/docker-entrypoint-initdb.d
Когда я запускаю docker-compose up
в первый раз, дамп восстанавливается в db.
Ответ 4
Я использовал метод docker-entrypoint-initdb.d(спасибо @Kuhess)
Но в моем случае я хочу создать свою БД на основе некоторых параметров, определенных в файле .env, поэтому я сделал эти
1) Сначала я определяю файл .env примерно так в моем корневом каталоге проекта docker
MYSQL_DATABASE=my_db_name
MYSQL_USER=user_test
MYSQL_PASSWORD=test
MYSQL_ROOT_PASSWORD=test
MYSQL_PORT=3306
2) Затем я определяю свой файл docker-compose.yml. Поэтому я использовал директиву args для определения переменных среды и установил их из .env файла
version: '2'
services:
### MySQL Container
mysql:
build:
context: ./mysql
args:
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
ports:
- "${MYSQL_PORT}:3306"
3) Затем я определяю папку mysql, которая включает файл Docker. Итак, файл Dockerfile это
FROM mysql:5.7
RUN chown -R mysql:root /var/lib/mysql/
ARG MYSQL_DATABASE
ARG MYSQL_USER
ARG MYSQL_PASSWORD
ARG MYSQL_ROOT_PASSWORD
ENV MYSQL_DATABASE=$MYSQL_DATABASE
ENV MYSQL_USER=$MYSQL_USER
ENV MYSQL_PASSWORD=$MYSQL_PASSWORD
ENV MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD
ADD data.sql /etc/mysql/data.sql
RUN sed -i 's/MYSQL_DATABASE/'$MYSQL_DATABASE'/g' /etc/mysql/data.sql
RUN cp /etc/mysql/data.sql /docker-entrypoint-initdb.d
EXPOSE 3306
4) Теперь я использую mysqldump для вывода моего db и поместите файл data.sql в папку mysql
mysqldump -h <server name> -u<user> -p <db name> > data.sql
Файл - это обычный файл дампа sql, но в начале я добавляю 2 строки, чтобы файл выглядел следующим образом:
--
-- Create a database using `MYSQL_DATABASE` placeholder
--
CREATE DATABASE IF NOT EXISTS `MYSQL_DATABASE`;
USE `MYSQL_DATABASE`;
-- Rest of queries
DROP TABLE IF EXISTS `x`;
CREATE TABLE `x` (..)
LOCK TABLES `x` WRITE;
INSERT INTO `x` VALUES ...;
...
...
...
Итак, что случилось с тем, что я использовал команду "RUN sed -i '/MYSQL_DATABASE/' $MYSQL_DATABASE '/g'/etc/mysql/data.sql" для замены заполнителя MYSQL_DATABASE
именем моей БД что я установил его в .env файл.
|- docker-compose.yml
|- .env
|- mysql
|- Dockerfile
|- data.sql
Теперь вы готовы создать и запустить свой контейнер
Ответ 5
Вы также можете посмотреть сервис с помощью docker-compose:
https://docs.docker.com/compose/wordpress/#build-the-project
с этим, mysql можно подключить к вашему приложению