我怎么能从主机访问命名卷?

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

Kitematic

然后我有这些错误/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)

我究竟做错了什么?

Dan*_*owe 9

卷层次结构

容器中的数据是一种层次结构.它是这样的.

1.图像的一部分

这是最低级别,其中数据位于只读,不可变图像本身.

2.在读写层中

从图像启动容器后,会在现有图像层的顶部添加读写层.如果在容器中更改,添加或删除了任何内容,则默认情况下会在此处写入.

第1层中此层覆盖数据的更改.

3. Docker卷

在您的示例中,您已在Docker中创建了一个卷

VOLUME /var/lib/mysql
Run Code Online (Sandbox Code Playgroud)

这将在Docker中创建一个卷,可以重复使用,持久化,在容器之间共享等.如果/var/lib/mysql第1层中有任何内容,则此卷的内容将覆盖.如果在容器中进行更改,则会在卷中进行更改(跳过第2层).

4.外部卷

最后,我们有可以在容器中安装的外部目录.这会覆盖所有其他人.

由于它们基于外部目录,因此可以从外部轻松访问容器中所做的任何更改.这可能就是你尝试这种方法的原因.

你怎么了

您从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.

  • 或者只是一个docker cp (2认同)
  • @CarlosRafaelRamirez真的,这更简单......我编辑了使用`docker cp`的答案.谢谢! (2认同)