Ben
Ben

Reputation: 4299

Docker exec quoting variables

I'd like to know if there's a way to do this

Let's say the dockerfile contains this line, that specifies path of an executable

ENV CLI /usr/local/bin/myprogram

I'd like to be able to call this program using ENV variable name through exec command.

For example docker exec -it <my container> 'echo something-${CLI} Expecting something-/usr/local/bin/myprogram

However that returns:

OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "exec: \"${CLI} do something\": executable file not found in $PATH": unknown

Upvotes: 13

Views: 12833

Answers (2)

masseyb
masseyb

Reputation: 4140

In it's original revision docker exec -it <my container> '${CLI} do something' with the expectation that ${CLI} will be substituted with /usr/local/bin/myprogram (as the exec COMMAND) and everything after passed as ARG's to /usr/local/bin/myprogram will not work, this is clearly documented: https://docs.docker.com/engine/reference/commandline/exec/

COMMAND should be an executable, a chained or a quoted command will not work. Example:

docker exec -ti my_container "echo a && echo b" will not work, but

docker exec -ti my_container sh -c "echo a && echo b" will.

Following the documentation, this will work as expected: docker exec -ti my_container sh -c "${CLI} foo", ${CLI} will be be executed after variable expansion and the argument(s) passed to the shell script set in ${CLI} (e.g. sh -c /usr/local/bin/myprogram foo).

Alternatively you could set the ENTRYPOINT to your script and pass in arguments with CMD or at the command line with docker run for example:

Given the below directory structure:

.
├── Dockerfile
└── example.sh

The Dockerfile contents:

FROM ubuntu:18.04
COPY example.sh /bin
RUN chmod u+x /bin/example.sh
ENTRYPOINT ["/bin/example.sh"]
CMD ["bla"]

And the example.sh script contents:

#!/bin/bash
echo $1

The CMD specified in the Dockerfile after the ENTRYPOINT will be the default argument for your script and you can override the default argument on the command line (assuming that the image is built and tagged as example:0.1):

user@host> docker run --rm example:0.1
bla
user@host> docker run --rm example:0.1 "arbitrary text"
arbitrary text

Note: this is my go to article for differences between ENTRYPOINT and CMD in Dockerfile's: https://medium.freecodecamp.org/docker-entrypoint-cmd-dockerfile-best-practices-abc591c30e21

Upvotes: -3

Ben
Ben

Reputation: 4299

Ok, I found a way to do it, all you need to do is evaluate command with bash

docker exec -it <container id> bash -c 'echo something-${CLI}'

returns something-/usr/local/bin/myprogram

If the CLI environment variable is not already set in the container, you can also pass it in such as:

docker exec -it -e CLI=/usr/local/bin/myprogram <container id> bash -c 'echo something-${CLI}'

See the help file:

 docker exec --help

 Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

 Run a command in a running container

Options:
-d, --detach               Detached mode: run command in the background
-e, --env list             Set environment variables
....

Upvotes: 23

Related Questions