调用子目录bash脚本时Docker构建相对路径问题求助
问题场景回顾
你的目录结构是这样的:
. ├── build.sh └── dir ├── build.sh └── Dockerfile
上层build.sh内容:
#!/bin/bash ./dir/build.sh
下层build.sh内容:
#!/bin/bash docker build -t test .
运行上层脚本时抛出错误:
unable to prepare context: unable to evaluate symlinks in Dockerfile path: GetFileAttributesEx C:\Dockerfile: The system cannot find the file specified.
问题根源
当你在项目根目录运行上层build.sh时,当前工作目录始终是根目录,并没有因为调用./dir/build.sh而自动切换到dir目录。下层脚本里的docker build -t test .是把当前工作目录(根目录)作为构建上下文,Docker会在根目录下找Dockerfile——但你的Dockerfile明明在dir里,自然找不到啦!
保留相对路径的解决方案
这里有几种靠谱的方法,都能保留相对路径逻辑:
方法1:让下层脚本自动切换到自身所在目录
这是最健壮的方案,让下层脚本自己处理路径,不管从哪里调用都能正常工作。修改dir/build.sh:
#!/bin/bash # 切换到当前脚本所在的目录 cd "$(dirname "$0")" docker build -t test .
$(dirname "$0")会获取当前脚本文件的绝对路径所在目录,比如如果你的脚本在C:\project\dir\build.sh,这个命令就会返回C:\project\dircd到这个目录后,.就指向dir目录,Docker就能找到里面的Dockerfile了
方法2:在Docker构建命令中明确指定Dockerfile路径和上下文
如果不想切换目录,也可以直接给docker build命令指定Dockerfile的位置和构建上下文。修改dir/build.sh:
#!/bin/bash docker build -t test -f "$(dirname "$0")/Dockerfile" "$(dirname "$0")"
-f参数指定Dockerfile的路径,$(dirname "$0")/Dockerfile就是脚本所在目录下的Dockerfile- 最后一个参数是构建上下文,这里指定为脚本所在目录,确保Docker能访问到上下文里的所有文件
方法3:在上层脚本中先切换目录再执行下层脚本
如果你只需要从上层脚本调用下层脚本,也可以在上层脚本里先切换到dir目录:
#!/bin/bash cd dir && ./build.sh
这样执行下层脚本时,工作目录已经是dir了,下层的docker build -t test .就能正常找到Dockerfile。
推荐方案
优先选方法1,因为它让下层脚本具备独立性,不管是从上层脚本调用,还是直接在dir目录下运行,都能正常工作,不会依赖调用者的工作目录。
内容的提问来源于stack exchange,提问作者Tuomas Toivonen

