How to effect side effects in pipe

2

1

I'm running minikube as a local test environment and using docker multi-stage builds to build my containers. Minikube runs a version of docker that doesn't support multi-stage builds. Minikube suggests you use the built-in docker environment to build containers as follows:

#!/usr/bin/env bash
eval $(minikube docker-env)
docker build

Because I need to use the local docker instance to build, I've found docker save/load. This means I need to do the following:

#!/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

However, docker load can read a file from stdin. If I could pipe the output from my docker host to a remote docker host I could do this without modifying/polluting my users' environments. So I was wondering whether there was some way to load the minikube env within a pipe environment. I've found the following works, but of course both docker hosts are the same:

docker save $IMG | env -i docker load

But I'd like something like the following (psuedo-code, I guess)

docker save $IMG | env -i side_effects(eval $(minikube docker-env)) docker load

I've tried simply inserting the command (didn't really expect this to work):

docker save $IMG | env -i eval $(minikube docker-env) docker load

And making a function to load the values:

function load_env { eval $(minikube docker-env) }
docker save $IMG | env -i load_env() docker load

Neither worked. I'm not that sure, but I presume eval was receiving the piped data. And eval doesn't use stdin. The latter caused a syntax error.

Finally, I could do something like this:

#/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

But as this has a lot of interacting interfaces, it will likely begin to fail as soon as one of them changes.

Edit: I've found an improvement on the above, I'd argue it's probably less fragile, but still more so than ideal:

dockerenv=$(minikube docker-env | sed 's/export//g' | sed 's/^#.*$//g' | sed 's/"//g')
docker save $IMG | env -i $dockerenv docker load

So really what I'm asking is: is there a robust way to avoid any temporary files or environment pollution on my users' machines? (If anyone has a better title for this question please change it- it's only one way to solve my problem).

mkingston

Posted 2017-06-21T13:07:30.870

Reputation: 372

Answers

1

Found a simple answer here: https://stackoverflow.com/a/44207110.

docker save $IMG | (eval $(minikube docker-env) && docker load)

snapshoe

Posted 2017-06-21T13:07:30.870

Reputation: 939

Re-reading my question, I can't believe how off-target my title was. What state of mind was I in?! Anyway, if anyone wants to test if this will work minimally, the following will help: echo "blah" | (eval $(touch side_effect) && tr -d '\n') – mkingston – 2017-10-26T16:11:43.417