Как я могу получить доступ к названному тому с хоста?
Я новичок в мире Docker и пытаюсь достичь чего-то, что можно считать тривиальным. Тем не менее, многие новички пытаются сохранить свои данные при использовании Docker.
Я создал собственное изображение, используя Dockerfile. Контейнер запускает сервер MySQL и... да, вы уже догадались: я хотел бы сохранить данные.
Вот мой Dockerfile:
FROM debian:8.7
ENV MYSQL_ROOT_PASSWORD=test
RUN apt-get update -y && apt-get install -y apt-utils && \
echo "mysql-server mysql-server/root_password password $MYSQL_ROOT_PASSWORD" | debconf-set-selections && \
echo "mysql-server mysql-server/root_password_again password $MYSQL_ROOT_PASSWORD" | debconf-set-selections && \
apt-get install -y mysql-server mysql-client && service mysql start
CMD service mysql start && /bin/bash
VOLUME /var/lib/mysql
EXPOSE 3306
Я создаю и запускаю образ таким образом:
docker build -t mysql-persist-test:0.1 .
docker run -dt -v database_volume:/var/lib/mysql mysql-persist-test:0.1
Пока все работает как положено, включая базу данных.
Однако, скажем, я хочу получить данные на моем хост-компьютере (Windows 10, я установил Docker через Docker Toolbox).
Я "привязываю" локальную папку к названному тому с помощью Kitematic (см. Ниже), контейнер автоматически перезагружается и... все сломано! Все файлы в /var/lib/mysql
каталог был удален. Некоторые были воссозданы с владельцем staff
вместо mysql
,
Тогда у меня есть эти ошибки в /var/log/mysql/error.log
:
...
/usr/sbin/mysqld: Table 'mysql.plugin' doesn't exist
170328 16:03:13 [ERROR] Can't open the mysql.plugin table. Please run mysql_upgrade to create it.
...
170328 16:03:13 InnoDB: Database was not shut down normally!
InnoDB: Starting crash recovery.
...
170328 16:03:13 InnoDB: Starting an apply batch of log records to the database...
InnoDB: Progress in percents: 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
InnoDB: Apply batch completed
...
170328 16:03:14 [ERROR] Fatal error: Can't open and lock privilege tables: Table 'mysql.host' doesn't exist
Что я делаю неправильно?
1 ответ
Иерархия томов
Данные в контейнерах находятся в некоторой иерархии. Это идет так.
1. часть изображения
Это самый нижний уровень, где данные находятся в неизменяемом изображении только для чтения.
2. в слое чтения-записи
Когда вы запускаете контейнер из изображения, поверх существующих слоев изображения добавляется слой для чтения и записи. Если что-то изменилось, добавлено или удалено в контейнере, по умолчанию это написано здесь.
Изменения в этом слое перекрывают данные в слое 1.
3. Объемы докеров
В вашем примере вы создали том в Docker с
VOLUME /var/lib/mysql
Это создаст том в Docker, который можно будет повторно использовать, сохранить, совместно использовать между контейнерами и т. Д. /var/lib/mysql
в слое 1 содержимое этого тома переопределяется. Если вы вносите изменения в контейнер, они вносятся в объеме (пропуская слой 2).
4. Внешние тома
Наконец, у нас есть внешние каталоги, которые вы можете монтировать внутри контейнера. Это отменяет все остальные.
Поскольку они основаны на внешнем каталоге, любые изменения, сделанные в контейнере, будут легко доступны извне. Вероятно, именно поэтому вы попробовали этот подход.
Что с тобой случилось
Вы начали с тома Docker (уровень 3), а затем изменили его на внешний том (уровень 4). Так как уровень 4 переопределяет уровень 3, то, что происходит, является содержимым вашего внешнего каталога (вероятно, без содержимого), переопределяет том Docker. Поэтому контейнер просто видит пустой каталог.
Ваши файлы все еще там. Просто отмените внешнее монтирование и вернитесь к тому Docker; они будут ждать там.
Как вытащить свои файлы
РЕДАКТИРОВАТЬ: как отмечает Карлос в комментариях, docker cp
проще, редактируя, чтобы использовать этот подход вместо этого.
docker cp <container-id>:/var/lib/mysql ./mydata
Это скопирует содержимое /var/lib/mysql
в папку mydata
,