moby / moby/buildkit

Add support for using `ARG`s in `ENTRYPOINT`

Open
#4,881 2 comments 13 reactions 1 assignee View on GitHub

@thompson-shaun is already working on this.

Since Oct 3, 2024.

area/dockerfile needs/maintainer-decision
Dominant language
Go
Stars
10.3k
Forks
1.5k
Avg merge
1d 23h
Merged PRs (30d)
48

Description

This issue is a moved one from moby/moby#18492 to here, since by @thaJeztah's comment, this here is now the correct repo to implement the feature.

There are 20 comments/posts in the original issue. My personal implementation proposal is in the second to last comment.

Here is a repost of all those comments, so that @tonistiigi isn't going to close this issue again without reading any of its related content (see #4841).

The 20 comments/posts from the original issue (click to expand)
Description of problem:

Previously defined variable with ARG is not substituted in ENTRYPOINT.

Environment details: physical, gentoo, zfs storage, zsh

$ docker version
Client:
 Version:      1.9.0
 API version:  1.21
 Go version:   go1.4.2
 Git commit:   76d6bc9
 Built:        
 OS/Arch:      linux/amd64

Server:
 Version:      1.9.0
 API version:  1.21
 Go version:   go1.4.2
 Git commit:   76d6bc9
 Built:        
 OS/Arch:      linux/amd64

$ docker info
Containers: 60
Images: 830
Server Version: 1.9.0
Storage Driver: zfs
 Zpool: data
 Zpool Health: ONLINE
 Parent Dataset: data/docker
 Space Used By Parent: 103388532736
 Space Available: 805944717312
 Parent Quota: no
 Compression: off
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 4.0.9-stable
Operating System: Gentoo/Linux
CPUs: 4
Total Memory: 15.59 GiB
Name: tecknack-corin
ID: JXJV:BP5E:T547:PZTF:4JSO:6SV5:B7EO:XA3U:EPV7:7Z5H:BS2Y:SAV7

$ uname -a
Linux tecknack-corin 4.0.9-stable #19 SMP Tue Oct 20 19:16:00 AEDT 2015 x86_64 Intel(R) Core(TM) i7-5500U CPU @ 2.40GHz GenuineIntel GNU/Linux
Steps to Reproduce:

How reproducible: Always

  1. Create Dockerfile
    FROM tianon/true # anything will do
    ARG type
    COPY entrypoint.sh /$type # again anything will do, e.g. `exec sh`
    ENTRYPOINT /$type
    
  2. Build: docker build --build-arg type=test -t test .
  3. Inspect: docker inspect '--format={{.Config.Entrypoint}}' test
  4. Run: docker run test
Actual Results:
  1. {[/bin/sh -c /$type]}
  2. /bin/sh: 1: /: Permission denied
Expected Results:
  1. {[/bin/sh -c /test]}
  2. Whatever is defined by entrypoint.sh.
Additional info:

COPY produces the expected result (i.e. the file /test exists).

Oddly enough the following work-around seems to work but inspect still reports /$type.

Work-around:

Dockerfile:

FROM tianon/true
ARG type
COPY entrypoint.sh /$type
ENV type $type
ENTRYPOINT /$type

_Originally posted by @au-phiware in https://github.com/moby/moby/issues/18492#issue-120933664


          `ARG` instruct the build variables, and `ENV` instruct the environment variables in container running. I don't think `ARG` var will take effect in container running time.

Originally posted by @wenchma in https://github.com/moby/moby/issues/18492#issuecomment-162795260


          @wenchma it could be used to specify the entrypoint at build-time, but I think it can't be used with entrypoint and cmd by design (ping @duglin @mapuri).

Originally posted by @vdemeester in https://github.com/moby/moby/issues/18492#issuecomment-162804613


          I appreciate that `ARG` does not apply at runtime, however I expected that `ENTRYPOINT` would behave in the same fashion as `RUN`, in this regard. It just appears to be inconsistent behaviour to me... I thought that `ENTRYPOINT` was a build time setting. I mean if I wanted to execute a script that lived in an environment variable wouldn't I just write that in the `entrypoint.sh` file??

Originally posted by @au-phiware in https://github.com/moby/moby/issues/18492#issuecomment-162807604


          This is by design. Read http://docs.docker.com/engine/reference/builder/#environment-replacement 

ENTRYPOINT dockerfile instruction does not use any ENV nor ARG.

The reason that your workaround works is that your entrypoint is not JSON so its channel through shell.

Originally posted by @ghost in https://github.com/moby/moby/issues/18492#issuecomment-162857330


          Its important to understand how env vars are set when we process a RUN.  We don't touch any `$xxx` on the RUN command directly, we just pass it on to the shell and its the shell that will convert `$xxx` into whatever value xxx may have.  Note that if you used the JSON format of RUN then `$xxx` would not have any env var substitution processing done at all because there's no shell.

Its the equivalent of:

FOO=bar sh -c "/bin/some-command"

While CMD and ENTRYPOINT are parsed at build-time, they are not executed at build-time. So, since ARG only sets a build-time env var, when CMD and ENTRYPOINT are actually executed (at image runtime) the value of any ARG env var is no longer present.

Originally posted by @duglin in https://github.com/moby/moby/issues/18492#issuecomment-162869083


          Given this is working as designed I'm going to close the issue. If you think there's something we may need to revisit go ahead and reopen it, or keep the chat going.

Originally posted by @duglin in https://github.com/moby/moby/issues/18492#issuecomment-162922441


          @villlem can you please let me know if the solution I have here is a stable solution?

http://stackoverflow.com/questions/40902445/using-variable-interpolation-in-string-in-docker/40902661#40902661

I noticed your comment:

"ENTRYPOINT dockerfile instruction does not use any ENV nor ARG.
The reason that your workaround works is that your entrypoint is not JSON so its channel through shell."

So maybe you can provide a better answer to that SO question than mine.

Originally posted by @ORESoftware in https://github.com/moby/moby/issues/18492#issuecomment-264076309


          This issue showed up first for me when googling "dockerfile use arg in entrypoint", so it's a shame it doesn't explain _why_ this is by design. Being able to use an ARG in the ENTRYPOINT seems like a useful feature to me, so it would be really useful to understand why that's a bad idea before I start trying to work around it.

Originally posted by @tstibbs in https://github.com/moby/moby/issues/18492#issuecomment-317453002


          @tstibbs as explained above, the entrypoint is evaluated at _runtime_ If you want to parameterise it you can still store the value of an `ARG` in an `ENV` var, which _is_ persisted in the image, so could be used at runtime.

Originally posted by @thaJeztah in https://github.com/moby/moby/issues/18492#issuecomment-317495201


          > @tstibbs as explained above, the entrypoint is evaluated at runtime.

Yes, I think we all know that ENTRYPOINT is evaluated at runtime. However, a major potential of ARG is to reduce the need for templating solutions to generate Dockerfiles.

When docker build is executed, there's no reason that ENTRYPOINT can't be updated to reflect the hard-coded insertion of ARG, during build time.

For example:

ARG MY_CMD=whoami
SHELL ["/bin/bash", "-c"]
ENTRYPOINT ${MY_CMD}

Current behavior: docker inspect my_image | grep -A5 Entrypoint

"Entrypoint": [
    "/bin/bash",
    "-c",
    "${MY_CMD}"
],

Desired behavior: docker inspect my_image | grep -A5 Entrypoint

"Entrypoint": [
    "/bin/bash",
    "-c",
    "whoami"
],

This doesn't seem that conceptually challenging to me.

Originally posted by @dejayc in https://github.com/moby/moby/issues/18492#issuecomment-327928345


          Changing that would be a huge breaking change, take for example;
ENTRYPOINT ["/bin/bash", "-c", "echo $FOOBAR"]

Running such an image with;

docker run -e FOOBAR=hello my-image

Should expand $FOOBAR at runtime, not baked into the image. If you need something to pre-process Dockerfiles, I think that's out of scope for the core functionality provided by the builder, and more something to a templating tool

Originally posted by @thaJeztah in https://github.com/moby/moby/issues/18492#issuecomment-328619623


          okay, not to get laughed off of here, but:
RUN ln -s ./${NAME} executable
ENTRYPOINT ["./executable"]

obviously the pattern can quickly devolve, but this just happens to be all i needed, personally

Originally posted by @nik-shornikov in https://github.com/moby/moby/issues/18492#issuecomment-347364597


          > If you need something to pre-process Dockerfiles, I think that's out of scope for the core functionality provided by the builder, and more something to a templating tool

Of course, in DevOps it's never enough to use just one tool. Let me guess, the tool that I use for templating, I should run that tool within Docker? That way, I can Docker my Docker while I'm Dockerizing my Dockerfile templating Docker.

Originally posted by @dejayc in https://github.com/moby/moby/issues/18492#issuecomment-367895867


          At the top I specify:
ARG PROJECT_NAME=MyAPI

Going through various multi-stage builds (build, test, publish, runtime) I use ${PROJECT_NAME} erverywhere to reference the project name.

How is it invalid to use the following, to be able to keep the same variable value everywhere in our Dockerfile ? ...

ENTRYPOINT ["dotnet", "${PROJECT_NAME}.exe"]

This belongs to a templating tool? What?

Originally posted by @gaui in https://github.com/moby/moby/issues/18492#issuecomment-376207145


          DevOps Mantra #12: If at first you don't succeed, try a templating tool.

Originally posted by @dejayc in https://github.com/moby/moby/issues/18492#issuecomment-381406981


          I want to follow DRY principle. To do so I would like to store a script name in `ARG` to generate the script with `RUN echo 'content' > ${script_name}` and then use the very same name in `ENTRYPOINT ["${script_name}"]`. In current Docker design I will have to create an extra envvar to work around Docker's limitation to read `ARG`s at runtime in `ENTRYPOINT` instruction. This could be improved.

Originally posted by @dmugtasimov in https://github.com/moby/moby/issues/18492#issuecomment-386884450


          Seems to me like this legacy issue is forcing folks to pass basic commands to sh -c just to get variable substitution.

Originally posted by @kalexmills in https://github.com/moby/moby/issues/18492#issuecomment-430708025


          > Changing that would be a huge breaking change, take for example;
ENTRYPOINT ["/bin/bash", "-c", "echo $FOOBAR"]

Running such an image with;

docker run -e FOOBAR=hello my-image

Should expand $FOOBAR at runtime, not baked into the image. If you need something to pre-process Dockerfiles, I think that's out of scope for the core functionality provided by the builder, and more something to a templating tool

@thaJeztah If this is considered a huge breaking change then introduce a new statement (or a modifier to the existing one) that prioritizes ARG should be a simple enough and satisfying solution. If an ARG is supplied at build time, its value will be hardcoded into the image (as it is everywhere else). If not, the reference is treated like it currently is.

For an ARG MY_ARG=foo statement, possible applications could look like:

ENTRYPOINT WITH ARGS ["./$MY_ARG"]
ENTRYPOINT --with-args ["./$MY_ARG"]
ARGSENTRYPOINT ["./$MY_ARG"]
ARGS_ENTRYPOINT ["./$MY_ARG"]
...

Given this is working as designed I'm going to close the issue. If you think there's something we may need to revisit go ahead and reopen it, or keep the chat going.

@duglin Please reopen the issue, so a practical solution can be implemented. Thanks!

Originally posted by @lauxjpn in https://github.com/moby/moby/issues/18492#issuecomment-2029064780


          This is a 9-Year old ticket, and the Dockerfile syntax syntax is now maintained by the BuildKit project. Any proposal for changes in the syntax should now be proposed there; https://github.com/moby/buildkit/issues.

Originally posted by @thaJeztah in https://github.com/moby/moby/issues/18492#issuecomment-2031413672


Since the original issue has additional cross references and user participation in form of a lot of emojis, I suggest to read that one instead of the reposted comments here.

There is a lot of interest in fixing this feature gap, so I am sure this issue will be respectfully considered. Thanks!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.