Docker Entrypoint无法接收传入kubectl命令参数的问题
问题背景
我一直在尝试构建一款可通过自定义OCI变量执行kubectl的Docker镜像,该镜像能够自动创建OCI配置文件,随后生成.kube/config文件。采用该方案的原因是管理的集群数量较多,每次在不同集群间切换十分耗时,且容易出错或混淆集群。
编写的Dockerfile中ENTRYPOINT配置如下:
FROM private.repo/oci-image:latest # Install Kubectl client RUN apt update && apt install -y curl gettext-base RUN curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.24.0/bin/linux/amd64/kubectl RUN chmod +x ./kubectl RUN mv ./kubectl /usr/local/bin/kubectl ... ... ... ENTRYPOINT ["/bin/bash", "-c", "./script.sh"]
对应的script.sh文件内容如下:
#!/bin/sh set -e cat $HOME/.oci/config-template | envsubst > $HOME/.oci/config yes | oci ce cluster create-kubeconfig --profile DEFAULT --cluster-id ${K8S_CLUSTER_ID} --file $HOME/.kube/config --region ${REGION} --token-version 2.0.0 --kube-endpoint PUBLIC_ENDPOINT yes | oci ce cluster create-kubeconfig --profile DEFAULT --cluster-id $K8S_CLUSTER_ID --file $HOME/.kube/config --region $REGION --token-version 2.0.0 --kube-endpoint PUBLIC_ENDPOINT exec "$@"
运行容器时传入kubectl命令的执行指令如下:
docker run -e ... oci-agent:v21 kubectl get nodes
执行后没有任何响应。尝试将脚本末尾的exec "$@"替换为exec "kubectl $@"后,仅输出kubectl的帮助说明,脚本只执行了kubectl本身,没有读取传入的命令参数,需要找到正确的实现方式。
故障根因
问题出在两处参数传递的逻辑错误:
- 用
/bin/bash -c "./script.sh"格式配置ENTRYPOINT时,bash只会执行-c后面紧跟的脚本字符串,Docker传入的CMD参数(即kubectl get nodes)不会自动传递给script.sh,导致脚本内的$@为空值,自然不会执行传入的kubectl命令。 - 改成
exec "kubectl $@"的写法存在语法错误:所有参数被拼接成单个字符串传递给kubectl,参数解析完全失效,kubectl识别不到有效子命令,就会直接输出帮助信息。
修复步骤
按以下两点修改即可正常运行:
- 修改Dockerfile的ENTRYPOINT配置,去掉多余的
bash -c包装,直接将脚本作为执行入口,确保CMD参数能直接透传给脚本:
如果必须保留bash调用的写法,需要在命令末尾显式透传参数,格式为# 提前给脚本加可执行权限,之前没配置的话补上这行 RUN chmod +x ./script.sh ENTRYPOINT ["./script.sh"]ENTRYPOINT ["/bin/bash", "-c", "./script.sh \"$@\"", "--"],前者更简洁,优先使用。 - 修正
script.sh末尾的执行逻辑,不要把$@和kubectl拼成单个字符串,直接原样透传所有参数即可:
这种写法下,传入的# 替换原来的exec "$@"行 exec kubectl "$@"get nodes参数会按原有位置正确传递给kubectl,不会出现参数丢失、解析错误的问题。
另外脚本里重复执行了两次完全相同的oci ce cluster create-kubeconfig命令,属于冗余操作,可以删掉其中一行,减少不必要的执行耗时。
内容的提问来源于stack exchange,提问作者joe1531
相关产品推荐
相关产品推荐

