Gui*_*TeK 4 mysql windows docker docker-volume kitematic
我是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
Run Code Online (Sandbox Code Playgroud)
我以这种方式构建和运行图像:
docker build -t mysql-persist-test:0.1 .
docker run -dt -v database_volume:/var/lib/mysql mysql-persist-test:0.1
Run Code Online (Sandbox Code Playgroud)
到目前为止,一切都按预期工作,包括数据库.
但是,假设我想在我的主机上检索数据(Windows 10,我通过Docker Toolbox安装了Docker).
我使用Kitematic将本地文件夹" 绑定 "到指定的卷(见下文),容器会自动重启并且......一切都坏了!目录中的所有文件都已删除.有些是与业主重新创建的而不是./var/lib/mysql staffmysql
然后我有这些错误/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
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
容器中的数据是一种层次结构.它是这样的.
这是最低级别,其中数据位于只读,不可变图像本身.
从图像启动容器后,会在现有图像层的顶部添加读写层.如果在容器中更改,添加或删除了任何内容,则默认情况下会在此处写入.
第1层中此层覆盖数据的更改.
在您的示例中,您已在Docker中创建了一个卷
VOLUME /var/lib/mysql
Run Code Online (Sandbox Code Playgroud)
这将在Docker中创建一个卷,可以重复使用,持久化,在容器之间共享等.如果/var/lib/mysql第1层中有任何内容,则此卷的内容将覆盖.如果在容器中进行更改,则会在卷中进行更改(跳过第2层).
最后,我们有可以在容器中安装的外部目录.这会覆盖所有其他人.
由于它们基于外部目录,因此可以从外部轻松访问容器中所做的任何更改.这可能就是你尝试这种方法的原因.
您从Docker卷(级别3)开始,然后更改为外部卷(级别4).由于级别4覆盖级别3,所以会发生外部目录的内容(可能没有内容),覆盖Docker卷.因此容器只看到一个空目录.
你的文件还在那里.只需撤消外部安装并返回Docker卷; 他们会在那里等.
编辑:正如卡洛斯在评论中指出的那样,docker cp更简单,编辑使用这种方法.
docker cp <container-id>:/var/lib/mysql ./mydata
Run Code Online (Sandbox Code Playgroud)
这会将内容复制/var/lib/mysql到文件夹中mydata.