moby: `ARG` and `ENTRYPOINT` don't play nice.
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
-
Create
Dockerfile
FROM tianon/true # anything will do ARG type COPY entrypoint.sh /$type # again anything will do, e.g. `exec sh` ENTRYPOINT /$type
-
Build:
docker build --build-arg type=test -t test .
-
Inspect:
docker inspect '--format={{.Config.Entrypoint}}' test
-
Run:
docker run test
Actual Results:
{[/bin/sh -c /$type]}
/bin/sh: 1: /: Permission denied
Expected Results:
{[/bin/sh -c /test]}
- 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
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Reactions: 5
- Comments: 17 (6 by maintainers)
okay, not to get laughed off of here, but:
obviously the pattern can quickly devolve, but this just happens to be all i needed, personally
Yes, I think we all know that
ENTRYPOINT
is evaluated at runtime. However, a major potential ofARG
is to reduce the need for templating solutions to generate Dockerfiles.When
docker build
is executed, there’s no reason thatENTRYPOINT
can’t be updated to reflect the hard-coded insertion ofARG
, during build time.For example:
Current behavior:
docker inspect my_image | grep -A5 Entrypoint
Desired behavior:
docker inspect my_image | grep -A5 Entrypoint
This doesn’t seem that conceptually challenging to me.
I appreciate that
ARG
does not apply at runtime, however I expected thatENTRYPOINT
would behave in the same fashion asRUN
, in this regard. It just appears to be inconsistent behaviour to me… I thought thatENTRYPOINT
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 theentrypoint.sh
file??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.
At the top I specify:
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 ? …
This belongs to a templating tool? What?
Seems to me like this legacy issue is forcing folks to pass basic commands to sh -c just to get variable substitution.
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.
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.
ARG
instruct the build variables, andENV
instruct the environment variables in container running. I don’t thinkARG
var will take effect in container running time.Changing that would be a huge breaking change, take for example;
Running such an image with;
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 toolDevOps Mantra #12: If at first you don’t succeed, try a templating tool.
I want to follow DRY principle. To do so I would like to store a script name in
ARG
to generate the script withRUN echo 'content' > ${script_name}
and then use the very same name inENTRYPOINT ["${script_name}"]
. In current Docker design I will have to create an extra envvar to work around Docker’s limitation to readARG
s at runtime inENTRYPOINT
instruction. This could be improved.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: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.