Pass ARG to ENTRYPOINT
Asked Answered
B

3

15

Say I have this in a Dockerfile:

ARG FOO=1
ENTRYPOINT ["docker.r2g", "run"]

where I build the above with:

docker build -t "$tag" --build-arg FOO="$(date +%s)" .

is there a way to do something like:

ENTRYPOINT ["docker.r2g", "run", ARG FOO]  // something like this

I guess the argument could also be passed with docker run instead of during the docker build phase?

Bullpen answered 19/6, 2018 at 4:53 Comment(0)
F
12

You could combine ARG and ENV in your Dockerfile, as I mention in "ARG or ENV, which one to use in this case?"

ARG FOO
ENV FOO=${FOO}

That way, you docker.r2g can access the ${FOO} environment variable.

I guess the argument could also be passed with docker run instead of during the docker build phase?

That is also possible, if it makes more sense to give FOO a value at runtime:

docker run -e FOO=$(...) ...
Freeness answered 19/6, 2018 at 5:48 Comment(4)
another solution might be to use --entrypoint with the docker run command and pass in the flag there? if that works, feel free to add that to your answer, idkBullpen
@AlexanderMills Yes, but if your entry point is still "docker.r2g", you can override CMD instead (since CMD are parameters passed to entrypoint)Freeness
I am not sure if you already saw my answer, but I had to try a lot of things to get this to work properly. Turns out, trying to include a list of arguments in a single env variable is not that robust, so passing arguments using $@ with bash, is probably the best way.Bullpen
thanks yeah I figured, I updated with a final addition, using docker run --entrypoint we can override ENTRYPOINT which is probably the absolute best way to pass in a dynamic list of arguments.Bullpen
B
6

This simple technique works for me:

FROM node:9
# ...
ENTRYPOINT dkr2g run "$dkr2g_run_args"

then we launch the container with:

docker run \
    -e dkr2g_run_args="$run_args" \
    --name "$container_name" "$tag_name"

there might be some edge case issues with spreading an env variable into command line arguments, but should work for the most part.

ENTRYPOINT can work either like so:

ENTRYPOINT ["foo", "--bar", "$baz"]  # $baz will not be interpreted

or like so:

ENTRYPOINT foo --bar $baz

not sure why the latter is not preferred - but env variable interpolation/interpretation is only possible using the latter. See: How do I use Docker environment variable in ENTRYPOINT array?

However, a more robust way of passing arguments is to use $@ instead of an env variable. So what you should do then is override --entrypoint using the docker run command, like so:

docker run --entrypoint="foo" <tag> --bar $@

To learn the correct syntax of how to properly override entrypoint, you have to look that up, to be sure, but in general it's weird - you have to put --entrypoint="foo" before the tag name, and the arguments to --entrypoint, after the tag name. weird.

Bullpen answered 19/6, 2018 at 19:6 Comment(1)
Using the shell version of ENTRYPOINT will execute command in /bin/sh -c, so /bin/sh will be PID 1 instead of the foo. Maybe a problem if you need the signals to be sent to foo. I believe tini solves that issue as a workaround.Chauffeur
U
2

In my case I needed this to be set on build time, meaning I didn't have the control over the docker run command so I really struggled with it because it didn't work to use it as ARG or ENV directives in the Dockerfile. So below was is my solution and it worked like a charm:

ENTRYPOINT export $(grep -v '^#' .env | xargs -d '\n') \
    && your_command_passing_the_variable ${FOO}

Basically what I did was copy the variables into a file and then export the values in the same bash instance created by the ENTRYPOINT directive. The value is captured and passed correctly to the command. Hopefully, this helps.

Note: If you need to put secrets in that file, do not add the file to the version control system (e.g. git), instead create the file during your pipeline and be sure to clean up any sensitive information.

Umbel answered 22/6, 2022 at 18:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.