【问题标题】:How am I supposed to access a named volume from the host?我应该如何从主机访问命名卷?
【发布时间】:2017-08-21 19:54:31
【问题描述】:

我是 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 Toolbox 安装了 Docker)。

我使用 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

我做错了什么?

【问题讨论】:

    标签: mysql windows docker docker-volume kitematic


    【解决方案1】:

    卷层次结构

    容器中的数据具有某种层次结构。是这样的。

    1。图片的一部分

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

    2。在读写层

    从图像启动容器后,会在现有图像层之上添加一个读写层。如果在容器中更改、添加或删除任何内容,默认情况下会写在此处。

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

    3。 Docker 卷

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

    VOLUME /var/lib/mysql
    

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

    4。外部卷

    最后,我们有可以挂载在容器内的外部目录。这会覆盖所有其他的。

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

    你怎么了

    您从 Docker 卷(级别 3)开始,然后更改为外部卷(级别 4)。由于级别 4 覆盖了级别 3,因此会发生外部目录的内容(可能没有内容),覆盖 Docker 卷。因此容器只会看到一个空目录。

    您的文件仍然存在。只需撤消外部挂载并返回到 Docker 卷;他们会在那里等着的。

    如何取出文件

    编辑:正如 Carlos 在 cmets 中指出的那样,docker cp 更简单,改为使用该方法进行编辑。

    docker cp <container-id>:/var/lib/mysql ./mydata
    

    这会将/var/lib/mysql 的内容复制到文件夹mydata

    【讨论】:

    • 或者只是一个docker cp
    • @CarlosRafaelRamirez 没错,这要简单得多...我编辑了答案以改用docker cp。谢谢!
    猜你喜欢
    • 2021-12-09
    • 2021-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-29
    • 1970-01-01
    • 1970-01-01
    • 2018-01-27
    相关资源
    最近更新 更多