Docker Machine在Mac上:无法在docker主机/docker-machine上看到挂载的卷?卷物理存储在哪里?

14

我使用Macbook Pro笔记本电脑,并安装了docker-machine(0.5.0)和docker-compose(1.5.0)来启动容器。

这意味着我正在使用docker-machine创建我的虚拟机boot2docker驱动的主机,它将运行我的docker守护进程并托管所有我的容器。

我认为我在主机和卷的概念上缺少了一些关键信息,因为它们涉及到Docker和文档。

这是我的docker-compose.yml文件(web只是构建php:5.6-apache镜像):

web:
  restart: "always"
  build: ./docker-containers/web
  ports:
    - "8080:80"
  volumes:
    - ./src:/var/www/html
  links:
    - mysql:mysql

mysql:
  restart: "always"
  image: mysql:5.7
  volumes_from:
    - data
  ports:
    - "3306:3306"
  environment:
    - MYSQL_ROOT_PASSWORD=XXX

data:
  restart: "no"
  image: mysql:5.7
  volumes:
    - /var/lib/mysql
  command: "true" 

关于卷的Docker Compose文件文档在这里:http://docs.docker.com/compose/compose-file/

它说明了对于卷-将路径作为卷挂载,可选地指定主机机器上的路径(HOST:CONTAINER),或访问模式(HOST:CONTAINER:ro)。

在这种情况下,“HOST”是指由docker-machine创建的VM,对吗?还是我的本地Macbook文件系统?将VM上的路径挂载到容器中?

web下我声明:

volumes:
  - ./src:/var/www/html
这将我的本地Macbook文件系统 /src 文件夹映射到Web容器中。如果我理解正确,它不应该将VM上的./src文件夹映射到Web容器中的/var/www/html吗?! 理论上,我认为我应该先将本地Mac文件系统文件夹./src复制到VM中,然后再进行此卷声明。但是docker-compose似乎会一次完成所有操作?感到困惑。
最后,我们可以看到我正在创建一个数据容器来保留我的MySQL数据。我已经声明:
volumes:
   - /var/lib/mysql
这是否应该在我的 HOST boot2docker VM 上创建一个名为 /var/lib/mysql 的文件夹,然后我就可以在 VM 上导航到此文件夹,是/否?当我使用 docker-machine 对我的机器进行 ssh,然后导航到 /var/lib 时,根本没有 mysql 文件夹!为什么它没有被创建呢?我的配置有问题吗?:/
先行致谢!非常感谢任何关于我在这里做错了什么的解释!

https://dev59.com/d2Ag5IYBdhLWcg3wlLqh#33404132 这个回答解决了你的问题吗? - Eli
1个回答

13

好的,这里有几个需要解决的问题。

我们先从 Docker 卷是什么开始(在这一点上请尽量不要考虑你的 MacBook 或 Vagrant 机器。只需注意 Docker 使用了一个不同的文件系统,无论它现在存在于何处): 也许可以这样想,Docker 中的每个卷本身都只是 Docker 内部文件系统的一部分。 容器可以使用这些卷,就像它们被挂载为“小硬盘”一样,并且可以在它们之间共享(或者被两个容器同时挂载,就像将某个 FTP 服务器的超快速版本安装到两个客户端一样 :P)。

原则上,您可以通过 Dockerfile 的 VOLUME 指令声明这些卷(仍然不要考虑您的计算机 / Vagrant 本身,只需考虑 Docker ;))。 例如,运行一个 Web 服务器容器,像这样:

FROM: nginx
VOLUME /www

现在,理论上,所有进入/www目录的内容都可以挂载和卸载到容器中,并且可以挂载到多个容器中。 现在单独使用Nginx很无聊,所以我们希望让php运行nginx存储的文件以产生更有趣的内容。=> 我们需要将该卷挂载到一些php-fpm容器中。 因此,在我们的compose文件中,我们会这样做

web:
  image: nginx
php:
  image: php-fpm
  volumes_from:
    - web
voila! 在nginx/web容器中通过VOLUME指令声明的每个文件夹都将在php容器中可见。值得注意的重要一点是,无论nginx的/www中有什么内容,都会覆盖php在/www中的内容。 如果你加上:ro,则php甚至不能写入该文件夹 :)
现在接近您的问题,还有第二种声明卷的方法,它不需要在Dockerfile中声明它们。这可以通过从主机挂载卷(在这种情况下为vagrant/boo2docker)来完成。让我们首先讨论在本地Linux上运行的情况。
如果您添加了以下内容:
volumes:
 - /home/myuser/folder:/folder

如果在你的docker-compose.yml文件中,加入/home/myuser/folder这一项,它将意味着此文件夹将被挂载到docker中。它会覆盖docker中/folder文件夹的任何内容,并且像/www文件夹一样能够被声明的应用程序访问。前提是它运行在Linux机器上的Docker daemon。

但实际上,你可能只需要以下建议来解决问题:

boot2docker/docker-machine/kitematic和所有这些工具处理这个问题的方式很简单,它们首先只是将一个卷挂载到vagrant机器上的docker容器中,然后也将其挂载到Mac文件系统中,希望一切都可以顺利进行.

现在我们在Mac上遇到的实际问题是权限。如果考虑到各个用户:root或其他用户处理容器中的文件,用户vagrant可能会处理vagrant主机中的文件,而Mac用户“skalfyfan”会处理Mac中的文件。他们都有不同的用户ID等,这就引发了许多问题,取决于你在Docker中实际运行的是什么。Mysql和Apache尤其麻烦,因为它们不在容器内运行为root。这意味着它们经常无法写入Mac文件系统。

在尝试下面的第二种方法之前,只需尝试将容器卷放置在Mac主目录下。这将解决大多数情况下的MySQL问题,这是我随着时间发现的。

另外,无需声明卷的完整路径,./folder就可以了,它是相对于docker-compose.yml文件所在的位置来读取的!

只需将compose-yml放在您的Mac用户文件夹中,这才是最重要的。没有chmod 777 -R命令会帮助你,它只需要在你的主文件夹下面即可 :)

但是,一些应用程序(例如Apache)仍然会让你感到困难。容器内运行的任何内容的用户ID与你的Mac用户ID不同,这会让你的生活变得很困难。为了解决这个问题,你需要以一种不冲突Mac权限的方式调整用户ID和用户组。你想要的组是staff,一个适用的UID可能是1000,因此你可以将以下内容放在Dockerfile的末尾:

RUN usermod -u 1000 www-data
RUN usermod -G staff www-data
RUN usermod -u 1000 mysql
RUN usermod -G staff mysql

所以,您现在已经了解到:

理论上我认为我应该先将本地mac文件系统文件夹./src复制到虚拟机上,然后再进行这个volume声明。不过docker-compose似乎神奇地一次性完成了所有操作?

没错,它就是这样做的:)

最后,我们可以看到我正在创建一个数据容器来保存我的mysql数据。我已经声明了: volumes: - /var/lib/mysql

这一点您理解有误:) 正如解释的那样,如果您没有指定主机文件夹,那么Docker将保留该路径。但是只针对此容器,并且所有内容都将保存在Docker文件系统中。根本没有写入主机!只有在容器文件夹之前指定主机文件夹时才会发生这种情况!

希望这能有所帮助 :)


是的,没错:停止容器很好,重新启动时数据仍然存在。 删除容器会导致卷中的数据也被删除。 这里有一个比较重要的提示: 卷仍然存在,但您失去了访问权限,它会占用您的硬盘空间=> 使用 -v 标志删除容器 :) - Armin Braun
等一下 :) 我觉得我在boot2docker中解释得很糟糕,这可能是学习这个的最糟糕的方法!(说真的,如果你可以通过Vagrant/Virtualbox之类的工具启动Debian或Ubuntu盒子,并在那里尝试这些事情,少了一个文件系统复杂性层 :).无论如何,进入实际问题: 我假设你在Mac上运行了docker-compose命令,对吗? 在这种情况下,您需要相对于Mac文件系统给出路径,就像我说的那样!此外,所有卷的路径都需要在您的Mac用户主文件夹中。否则它不会起作用。 docker ps -a的输出是什么? - Armin Braun
我的Mac上的docker-compose命令正确。我的项目文件夹是在我的用户目录下的几个子目录中(例如/Users/myname/dev/projectName)。我刚刚将我的数据容器更改为读取:volumes: - ./data/mysql:/var/lib/mysql,其中./data是我本地Mac上当前项目文件夹中的一个空目录。从docker ps -a的输出中可以看到web、mysql容器正在运行,而data容器已经Exited (0) X seconds ago - skålfyfan
太棒了!至少数据容器还在运行!尽管我设置了volumes: - ./data/mysql:/var/lib/mysql,但我仍然看不到我的主机VM中的./data文件夹中的任何内容。实际上,我猜这会将我本地./data/mysql文件夹中的任何内容映射到容器的/var/lib/mysql文件夹中,对吧?而不是相反吗?我只想让MySQL将所有数据存储在VM(如果不使用virtualbox,则为本地),并使容器读取和写入VM。那么,在这种情况下,我为什么不只使用Vagrant呢?哈哈! - skålfyfan
如果你只使用Linux :) => ,那么你不应该让它一直运行。但(至少在我记忆中),boot2docker需要数据容器运行,否则它无法正确转发到Vagrant。 但是,你可以将Mac映射到容器中,但不能将容器映射到Mac(一旦挂载,容器可以写入已挂载的主机路径)。 =>在我看来,独立的Vagrant非常方便,boot2docker和docker-machine的方便性并不值得麻烦。 - Armin Braun
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接