记录一次docker文件挂载困扰了我4个小时的问题。
Dynamic Grid是selenium-grid 4.0最新添加的功能。它能够按需启动 Docker 容器,这意味着它会在后台为每个新的会话请求启动一个 Docker 容器,在那里执行测试,当测试完成时,容器会被丢弃。
在部署selenium-grid镜像时需要将一个配置文件挂载到服务启动容器中,即为下面的config.toml
version: "3"
services:
node-docker:
image: selenium/node-docker:4.0.0
volumes:
- ./assets:/opt/selenium/assets
- ./config.toml:/opt/bin/config.toml
在windows下的docker-compose中这样部署是没问题的,但在linux上,因为docker版本问题没有docker-compose只能通过docker原生命令去启动容器。于是我的命令改成了这样:
docker run -d \
-v ./assets:/opt/selenium/assets \
-v ./config.toml:/opt/bin/config.toml \
selenium/node-docker:4.0.0
看似没有问题,把命令执行一下:
docker: Error response from daemon: create ./assets: "./assets" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed. If you intended to pass a host directory, use absolute path.
See 'docker run --help'.
报了错误,意思是不可以使用.
作为路径的开头,必须使用绝对路径。于是做了更改:
docker run -d \
-v $pwd/assets:/opt/selenium/assets \
-v $pwd/config.toml:/opt/bin/config.toml \
selenium/node-docker:4.0.0
重新执行:
这次镜像成功构造了,但在启动镜像时仍旧报错:提示没有找到这个配置文件。很奇怪,我查了一下其他同学的说法:
-v mount 文件(或文件夹)时,docker 记录的是该文件的 inode,并用 inode 追踪。当用 vim 编辑了文件后,这个文件的 inode 就变了,也就是说这个 default.conf 文件已经不是运行 docker run 时的那个 default.conf 文件了,容器中自然也就没了新的改动。 同时该 issue 的 opener 使用的是 sed -i 修改,也会使 inode 发生变化,sed -i 的机制是创建一个新的临时文件,修改完后在重命名。对此,官方的建议是挂载文件夹,而不是文件。
根据他的说法我选择先从镜像中cp下来/opt/bin/config.toml
文件夹中的所有文件,然后再把整个/opt/bin
的文件挂载到镜像中。
执行如下命令cp文件到本地:
docker cp node-docker:/opt/bin ./
然后再执行一下代码:
docker run -d \
-v $pwd/assets:/opt/selenium/assets \
-v $pwd/bin:/opt/bin \
selenium/node-docker:4.0.0
这次说找不到/opt/bin/entry_point.sh
文件,这个文件应该在bin下,我在本地看了一下bin的目录并没有缺少这个文件啊。
在百度google查了好久挂载文件的问题都没有遇到类似的状况,我想到之前打包镜像时有一个命令叫docker inspect
,之前是用来检查镜像是否commit成功而不是使用的原始的镜像。是在没办法我试了一下:
docker inspect node-docker
果然好用,在里面有个叫mount也就是挂载情况的对应json字段:
可以发现挂载文件的情况是把根目录下的bin挂载到了镜像中,可我们回顾一下我们的命令没错啊,使用的是$pwd
去动态挂载,挂载的结果上看是挂载失败了,这个$pwd
命令整个都没有输出。在cmd里试一下:
空空如也啥都没有,心态炸了。回想起前天学的linux shell命令处理,是需要在$pwd
加上()
的,这样才视为pwd是个命令,然后把pwd带回的路径返回输出。而我这样直接去使用$pwd
linux当这个pwd为一个变量,从本地去找这个变量,我们没有定义他当然就空空如也呀。于是我按照docker-compose的格式重新挂载文件试一下好不好用:
成功了!
总结
linux中想使用相对路径挂载文件,可以使用$(pwd)
命令代替./
docker inspect
命令可以检查当前镜像/容器的状态
心得
其实最终如何解决是很重要,更重要的是这个过程中掌握了shell命令在实际开发场景的具体应用以及docker的一些细节方法,通过这些方法,相信可以解决以后遇见的绝大部分相似的问题,再也不会让人头秃了!