我正在运行 minikube 作为本地测试环境,并使用 docker 多阶段构建来构建我的容器。Minikube 运行的 docker 版本不支持多阶段构建。Minikube 建议您使用内置的 docker 环境来构建容器,如下所示:
#!/usr/bin/env bash
eval $(minikube docker-env)
docker build
因为我需要使用本地docker实例进行构建,所以我找到了docker save/load。这意味着我需要执行以下操作:
#!/usr/bin/env bash
docker build
docker save $IMG > /tmp/container.tar
eval $(minikube docker-env) # set up docker env vars
docker load -i /tmp/container.tar
eval $(minikube docker-env -u) # clean up env
但是,docker load 可以从 stdin 读取文件。如果我可以将输出从我的 docker 主机管道传输到远程 docker 主机,我就可以做到这一点而无需修改/污染我的用户的环境。所以我想知道是否有某种方法可以在管道环境中加载 minikube 环境。我发现以下方法有效,但当然两个 docker 主机是相同的:
docker save $IMG | env -i docker load
但我想要类似下面的东西(我猜是伪代码)
docker save $IMG | env -i side_effects(eval $(minikube docker-env)) docker load
我尝试过简单地插入命令(没想到它会起作用):
docker save $IMG | env -i eval $(minikube docker-env) docker load
并创建一个函数来加载值:
function load_env { eval $(minikube docker-env) }
docker save $IMG | env -i load_env() docker load
两者都不起作用。我不太确定,但我推测 eval 正在接收管道数据。而且 eval 不使用 stdin。后者导致了语法错误。
最后,我可以做这样的事情:
#/usr/bin/env bash
hostenv=$(minikube docker-env | grep DOCKER_HOST | cut -f2 -d'='
certpath=$(minikube docker-env | grep DOCKER_CERT_PATH | cut -f2 -d'='
docker save $IMG | docker -H=$hostenv --tls=true --tlsverify=true \
--tlscacert=$certpath/ca.pem --tlscert=$certpath/cert.pem \
--tlskey=$certpath/key.pem
但由于它有很多交互的接口,只要其中一个接口发生变化,它就可能会开始失败。
编辑:我发现上述情况有所改进,我认为它可能不那么脆弱,但仍然比理想的情况更糟糕:
dockerenv=$(minikube docker-env | sed 's/export//g' | sed 's/^#.*$//g' | sed 's/"//g')
docker save $IMG | env -i $dockerenv docker load
所以真的我问的是:有没有一种可靠的方法可以避免用户机器上出现任何临时文件或环境污染?(如果有人对这个问题有更好的标题请改变它-这是解决我的问题的唯一方法)。
答案1
在这里找到一个简单的答案:https://stackoverflow.com/a/44207110。
docker save $IMG | (eval $(minikube docker-env) && docker load)