Mac 上的 Docker 机器:在 docker 主机/docker-machine 上看不到已安装的卷?卷物理存储在哪里?
我在 Macbook Pro 笔记本电脑上运行 docker-machine (0.5.0) 和 docker-compose (1.5.0) 来启动我的容器.>
这意味着我正在使用 docker-machine 创建我的虚拟机 boot2docker 驱动的主机机器,它将运行我的 docker 守护进程并托管我的所有容器.
我想我在 HOSTS 和 VOLUME 的概念中遗漏了一些关键的东西,因为它们指的是 Docker 和文档.
这是我的 docker-compose.yml 文件(web 只是构建了 php:5.6-apache 镜像):
网站:重新启动:总是"构建:./docker-containers/web端口:- 8080:80"卷:- ./src:/var/www/html链接:- mysql:mysqlmysql:重新启动:总是"图像:mysql:5.7卷来自:- 数据端口:- 3306:3306"环境:- MYSQL_ROOT_PASSWORD=XXX数据:重新启动:否"图像:mysql:5.7卷:-/var/lib/mysql命令:真"
卷的 Docker Compose 文件文档在这里:http://docs.docker.com/compose/compose-file/
它声明了卷 - 将路径安装为卷,可选择指定主机上的路径 (HOST:CONTAINER) 或访问模式 (HOST:CONTAINER:ro).
在这种情况下,HOST 指的是由 docker-machine 创建的我的 VM,对吗?还是我本地的 macbook 文件系统?将我的 VM 上的路径挂载到容器?
在 web 下我声明:
卷:- ./src:/var/www/html
这是将我的 macbook pro 上的本地 macbook 文件系统 ./src 文件夹映射到我的 Web 容器.如果我的理解是正确的,它不应该将我的 VM 上的 ./src 文件夹映射到 /var/www/html网络容器?!从理论上讲,我认为我应该首先将我的本地 mac 文件系统文件夹 ./src 复制到我的 VM,然后我执行此卷声明.不过,似乎 docker-compose 神奇地一次完成了这一切?困惑
最后,我们可以看到我正在创建一个仅数据容器来保存我的 mysql 数据.我已经声明:
卷:-/var/lib/mysql
这不应该在我的 HOST boot2docker VM 上创建一个 /var/lib/mysql 文件夹,然后我可以导航到 VM 上的这个文件夹,是/否?当我使用 docker-machine ssh 进入我的机器,然后导航到 /var/lib 时,根本没有 NO mysql 文件夹?!为什么它没有被创建?我的配置有问题吗?:/
提前致谢!任何关于我在这里做错的解释将不胜感激!
解决方案好的,这里有几点需要解决.
让我们从什么是 docker 卷开始(此时尽量不要考虑您的 macbook 或 vagrant 机器.请注意,docker 使用不同的文件系统,此时它可能驻留在何处):也许可以这样想象,Docker 中的每个卷本身只是 Docker 使用的内部文件系统的一部分.容器可以使用这些卷,就像它们是小硬盘",可以由它们挂载并在它们之间共享(或由其中两个同时挂载,例如将某些 ftp 服务器的超快速版本挂载到两个客户端)或其他任何:P).
原则上,您可以通过 Dockerfile 的 VOLUME 指令声明这些卷(仍然不考虑您的计算机/vagrant 本身,只考虑 docker ;)).标准示例,像这样运行一个网络服务器容器:
来自:nginx音量/www
现在进入/www 的所有内容理论上都可以从容器中挂载和卸载,也可以挂载到多个容器.现在单独 Nginx 很无聊,所以我们想让 php 运行 nginx 存储的文件以产生一些更有趣的内容.=> 我们需要将该卷挂载到某个 php-fpm 容器中.因此在我们的撰写文件中,我们会这样做
网站:图片:nginxphp:图片:php-fpm卷来自:- 网络
=> 瞧!在 nginx/web 容器中由 VOLUME 指令声明的每个文件夹都将在 php 中可见.这里要注意的重要一点是,nginx 的/www 中的任何内容都将覆盖/www 中 php 中的任何内容.如果你把:ro, php 甚至不能写入那个文件夹:)
现在接近您的问题,有第二种声明卷的方法,不需要在 Dockerfile 中声明它们.这可以通过从主机挂载卷来完成(在这种情况下是你的 vagrant/boo2docker 东西).让我们先像在原生 Linux 上运行一样讨论这个问题.
如果您要输入以下内容:
卷:-/home/myuser/folder:/文件夹
在你的 docker-compose.yml 中,这意味着/home/myuser/folder 现在将被挂载到 docker 中.它将覆盖 docker 在/folder 中的任何内容,就像/www 也可以从声明它的东西访问.现在运行 docker 守护进程的 Linux 机器.
理论就到此为止了:),实际上您可能只需要以下建议就可以让您的工作顺利进行:):
boot2docker/docker-machine/kitematic 和所有这些事情处理这个问题的方式很简单,他们首先只是将流浪机器中的一个卷挂载到 docker 容器,然后他们也简单地将这个东西挂载到你的Mac 文件系统,希望一切顺利 :P
现在,我们所有人在 Mac 上使用这个(或者只是试图帮助他们的同事进入甜蜜的 Docker 世界:P)面临的实际问题是权限.我的意思是想一想(root 或其他一些用户处理容器中的文件,用户 vagrant 可能处理 vagrant 主机中的文件,然后你的 Mac 用户skalfyfan"在 Mac 中处理这些文件.它们都有不同的用户 ID 和诸如此类的东西 => 随之而来的许多问题,在某种程度上取决于您在 Docker 中实际运行的内容.Mysql 和 Apache 尤其痛苦,因为它们不在容器中以 root 身份运行.这意味着,它们通常无法写入 Mac 文件系统.
在尝试下面的第二种方法之前,只需尝试将容器卷放在 Mac 主目录下.随着时间的推移,这将在大多数情况下解决 MySQL 的问题.顺便说一句:无需声明卷的完整路径 ./folder 就可以了,并且可以相对于 docker-compose.yml 所在的位置读取!
只需将 compose-yml 放在您的 Mac 用户文件夹中,这很重要.没有 chmod 777 -R :P 会在这里帮助你,它只需要在你的主文件夹下:)
仍有一些应用程序(例如 Apache)仍然会给您带来困难.容器中运行的任何内容的用户 ID 与您的 Mac 用户 ID 不同这一事实会让您的生活陷入困境.为了解决这个问题,您需要以不与 Mac 权限冲突的方式调整用户 ID 和用户组.在 Mac 上你想要的组是员工,一个有效的 UID 是例如 1000.因此,您可以将其放在 Dockerfile 的末尾:
RUN usermod -u 1000 www-data运行 usermod -G 员工 www-data
或
RUN usermod -u 1000 mysql运行 usermod -G 员工 mysql
正如你现在了解到的:
<块引用>理论上我认为我应该被要求复制我的本地mac文件系统文件夹 ./src 首先到我的 VM,然后我做这个卷宣言.似乎 docker-compose 神奇地一次完成了这一切虽然?
没错,它就是这样做的:)
<块引用>最后,我们可以看到我正在创建一个仅数据容器来持久化我的mysql数据.我已经声明:卷:-/var/lib/mysql
这个你错了 :) 正如解释的那样,如果你不提供主机文件夹,那么 Docker 将保留这个路径.但仅针对此容器,所有内容都将保留在 docker 文件系统中.什么都没有写给主机!仅当您在容器文件夹之前指定主机文件夹时,才会发生这种情况!
希望这有帮助:)
Am on a Macbook Pro laptop and running docker-machine (0.5.0) and docker-compose (1.5.0) to get my containers going.
This means I'm using docker-machine to create my virtualbox boot2docker driven HOST machines, which will run my docker daemon and host all my containers.
I think I'm missing something critical with the concept of HOSTS and VOLUME, as they refer to Docker and the documentation.
This is my docker-compose.yml file (web simply builds the php:5.6-apache image):
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 file documention for volumes is here: http://docs.docker.com/compose/compose-file/
It states for volumes - Mount paths as volumes, optionally specifying a path on the host machine (HOST:CONTAINER), or an access mode (HOST:CONTAINER:ro).
HOST in this case refers to my VM created by docker-machine, correct? Or my local macbook file system? Mounting a path on my VM to a container?
Under web I declare:
volumes:
- ./src:/var/www/html
and this is mapping my local macbook file system ./src folder on my macbook pro to my web container. If my understanding is correct though, shouldn't it be mapping the ./src folder on my VM to /var/www/html within the web container?! In theory I think I should be required to COPY my local mac file system folder ./src to my VM first, and then I do this volume declaration. It seems docker-compose is magically doing it all at once though? confused
Lastly, we can see that I'm creating a data-only container to persist my mysql data. I've declared:
volumes:
- /var/lib/mysql
Shouldn't this create a /var/lib/mysql folder on my HOST boot2docker VM and I could then navigate to this folder on the VM, yes/no? When I use docker-machine to ssh into my machine, and then navigate to /var/lib, there is NO mysql folder at all?! Why is it not being created? Is there something wrong with my configuration? :/
Thanks in advance! Any explanations as to what I'm doing wrong here would be greatly appreciated!
解决方案Ok there's a couple of points that need to be addressed here.
Lets start with what a docker volume is(Try to not think about your macbook or the vagrant machine at this point. Just be mindful of the fact that the dockers use a different filesystem, where ever it may reside at this point ): Maybe imagine it like this, in and of itself every volume in Docker is just a part of the internal file system docker uses. The containers can use theses volumes, like they were "small harddrives" that can be mounted by them and also shared between them (or mounted by two of them at the same time, like mounting a super fast version of some ftp server to two clients or whatever :P ).
In principal you can declare these volumes ( still not thinking about your computer/vagrant itself, just the dockers ;) ) via the Dockerfile's VOLUME instruction. Standard example, run one webserver container like so:
FROM: nginx
VOLUME /www
Now everything that goes into /www can in theory be mounted and unmounted from a container and also mounted to multiple containers. Now Nginx alone is boring, so we want to have php run over the files that nginx stores to produce some more fun content. => We need to mount that volume into some php-fpm container. Ergo in our compose file we'd do this
web:
image: nginx
php:
image: php-fpm
volumes_from:
- web
=> voila! every folder declared by a VOLUME directive in the nginx/web container will be visible in the php one. Important point to note here, whatever is in nginx's /www, will override whatever php has in /www. If you put the :ro, php can't even write to that folder :)
Now moving close to your issue, there's a second way to declare volumes, that does not require them being declared in the Dockerfile. This can be done by mounting volumes from the host (in this case your vagrant/boo2docker thingy). Let's discuss this as though we're running on a native Linux first.
If you were to put something like:
volumes:
- /home/myuser/folder:/folder
in your docker-compose.yml, then this will mean that /home/myuser/folder will now be mounted into the docker. It will override whatever the docker has in /folder and just like the /www also be accessible from the thing that declared it. Now the Linux machine the docker daemon is running on.
So much for the theory :), in fact you probably just need the following advice to get your stuff going :):
The way boot2docker/docker-machine/kitematic and all these things deal with the issue is simply, that they first of all just mount a volume in the vagrant machine to the docker containers, and them simply also mount this thing into your Mac file system, hoping it will all work out :P
Now for the practical problem all of us using this (or just trying to help their coworkers into the world of sweet sweet Docker :P) on Mac are facing is permissions. I mean think about it ( root or some other user handles files in the container,the user vagrant might handle files in the vagrant host and then your Mac user "skalfyfan" handles those files in Mac. They all have different user id's and whatnot => many problems ensue with that, and somewhat depending on what you're actually running in Docker. Mysql and Apache are especially painful, because they do not run as root within the container. This means, they often have trouble writing to the Mac file system.
Before trying the second approach below, simply try putting your container volumes under you Mac home directory. This will resolve issues with MySQL in most cases as I have found over time. Btw: No need to declare full paths to volumes ./folder is fine and read relative to the place your docker-compose.yml resides!
Just put the compose-yml in your Mac users folder, that's all that matters. No chmod 777 -R :P will help you here, it just needs to be under your home folder :)
Still some apps ( Apache for example ) will still give you a hard time. The fact that the user id of whatever runs in the container differs from your Mac user id will make your life hell. In order to get around this, you need to adjust the user id as well as the user group in a way that doesn't conflict with your Mac's permissions. The group you want on a Mac is staff, a UID that works would be for example 1000. Hence you could put this at the end of your Dockerfile:
RUN usermod -u 1000 www-data
RUN usermod -G staff www-data
or
RUN usermod -u 1000 mysql
RUN usermod -G staff mysql
So as you have now learnt:
In theory I think I should be required to COPY my local mac file system folder ./src to my VM first, and then I do this volume declaration. It seems docker-compose is magically doing it all at once though?
Right on, it does that :)
Lastly, we can see that I'm creating a data-only container to persist my mysql data. I've declared: volumes: - /var/lib/mysql
This one you got wrong :) As explained, if you don't give a host folder, then Docker will persist this path. But only for this container and all will stay within the docker file system. Nothing is written to the host at all! This will always only happen if you give a host folder before the container folder!
Hope this helped :)
相关文章