使用make执行docker构建命令与直接在shell运行结果不一致如何解决
问题原因
出现执行差异的核心原因是Make默认的命令执行环境和交互终端的shell环境不一致,具体逻辑如下:
- Make执行构建规则内的命令时,默认调用
/bin/sh作为执行解释器,大部分发行版的/bin/sh是精简的dash实现,仅支持波浪号~出现在参数开头时的主目录扩展。你写的default=~/.ssh/id_rsa中~位于等号之后,不会被dash识别为主目录占位符,会被当成字面量字符处理,因此docker会尝试查找当前目录下名为~的子目录,自然找不到对应文件。 - 你直接在交互终端执行命令时,用的是bash/zsh这类功能更完整的shell,这类shell支持参数任意位置的波浪号扩展,会自动把
~替换成当前用户主目录的绝对路径,因此可以正常执行。
解决方案
以下是几种可行的解决方式,按需选择即可:
- 方案1:用
$HOME替代波浪号,注意Make规则中要对$转义(加额外的$符号,避免Make把它识别为自身的变量),修改后的Makefile规则如下:
build-docker: DOCKER_BUILDKIT=1 docker build --ssh default=$$HOME/.ssh/id_rsa -t my-app .
- 方案2:显式指定Make使用bash作为执行shell,在Makefile的开头添加一行配置即可,原有命令不需要修改:
SHELL := /bin/bash build-docker: DOCKER_BUILDKIT=1 docker build --ssh default=~/.ssh/id_rsa -t my-app .
- 方案3:如果本地启动了ssh agent,不需要显式指定密钥路径,直接简化命令即可,兼容性和安全性更好:
build-docker: DOCKER_BUILDKIT=1 docker build --ssh default -t my-app .
- 方案4:直接写密钥的绝对路径,缺点是移植性差,只能在当前用户的设备上使用:
build-docker: DOCKER_BUILDKIT=1 docker build --ssh default=/home/你的用户名/.ssh/id_rsa -t my-app .
内容的提问来源于stack exchange,提问作者RasmusN
相关产品推荐
相关产品推荐

