#mysql #docker
Вопрос:
Мне нужно сохранить свою базу данных из контейнера docker mysql, чтобы другие члены команды также могли работать над ней. До сих пор мы использовали это, и это работало просто отлично:
volumes:
- ./db/:/var/lib/mysql/
Однако папка /db была действительно грязной, потому что папка /mysql содержит все файлы mysql, а не только базу данных. Поэтому я попытался сохранить только папку базы данных:
volumes:
- ./db/:/var/lib/mysql/database/
Но, к сожалению, я продолжаю получать эту ошибку:
[ERROR] --initialize specified but the data directory has files in it. Aborting.
[ERROR] Aborting
Однако, несмотря на то, что говорится в ошибке, папка /db пуста (также нет скрытых файлов), поэтому я понятия не имею, в чем на самом деле заключается ошибка.
Я также попробовал другие подкаталоги внутри /mysql и получил тот же результат. Когда я возвращаю изменения обратно - ./db/:/var/lib/mysql/
, ошибка исчезает.
Полный докер-compose.yml:
mysql:
image: mysql:${MYSQL_VERSION:-latest}
restart: always
ports:
- "3306:3306"
volumes:
- ./db/:/var/lib/mysql/${DB_NAME}
networks:
- backend
environment:
MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASSWORD}"
MYSQL_DATABASE: "${DB_NAME}"
MYSQL_USER: "${DB_USERNAME}"
MYSQL_PASSWORD: "${DB_PASSWORD}"
container_name: ${PROJECT_PREFIX}_mysql
Ответ №1:
Есть несколько вещей, которые следует отметить в примере, которым вы поделились:
- Образ MySQL, который вы используете, фактически не «инициализирует» сервер базы данных до тех пор, пока он не будет впервые доставлен
up
(обычная практика, поскольку размер изображения остается относительно небольшим). - Контейнеры Docker не сохраняют никаких данных, если вы явно не смонтируете их с помощью
volumes
. Поэтому каждый раз, когда вы переключаетесь сdown
/up
, вы возвращаете контейнер в исходное состояние изображения. - Когда вы просматриваете
down
/up
, порядок операций выглядит следующим образом:- используется исходное состояние изображения
- крепления тома монтируются в следующем
- сценарии точки входа запускаются для вызова контейнера.
- В данном случае сценарии точки
3
входа MySQL «инициализируют» сервер базы данных , если/var/lib/mysql
каталог пуст, в противном случае он просто загрузит его из существующих файлов. - Когда вы монтируете
/var/lib/mysql
, это работает, потому что:- если каталог пуст, то он инициализируется
- если каталог не пуст, то он загружает состояние.
- Однако при подключении монтируется
/var/lib/mysql/database
только этот каталог, а другие важные данные не включаются в/var/lib/mysql
него , поскольку они не существуют в исходном образе. Оказывается, другие важные данные, которых не хватает, — это то, что проверяет MySQL, чтобы проверить, нужно ли ему «инициализировать» сервер базы данных или нет. Наконец, он пытается инициализироваться из-за отсутствующих данных, но если/var/lib/mysql
они не пусты, он выдает ошибку (вашу ошибку). В этом случае он не пуст, потому что вы смонтировалиdatabase
его в каталоге/var/lib/mysql
.
Ваши варианты в основном:
- Живите с подключением
/var/lib/mysql
и резервным копированием всего каталога (убедитесь, что вы делаете резервные копии только тогда, когда у вас естьdocker-compose down
!) - Создайте свой собственный файл Dockerfile с дополнительными
RUN
шагами для инициализации MySQL и уменьшите его, чтобы сервер базы данных был «инициализирован» и сохранен в образе. Однако я бы не рекомендовал это делать, так как: 1) размер вашего изображения docker будет намного больше, и 2) этот параметр подвержен проблемам с повреждением.