The simple reason is that the value of the secret is visible to anyone with the image by simply running history
on it.
Take this sample docker file:
FROM alpine
ARG secret
RUN echo "${secret}"
(Nice and simple, just to illustrate how you might use a secret.)
then we build it $ docker build --build-arg secret=S3CR3T - < Dockerfile
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM alpine
---> 13e1761bf172
Step 2 : ARG secret
---> Running in 695b7a931445
---> 5414c15a1cb6
Removing intermediate container 695b7a931445
Step 3 : RUN echo "${secret}"
---> Running in c90cf0d1414b
s3cr3t
---> f2bcff49ac09
Removing intermediate container c90cf0d1414b
Successfully built f2bcff49ac09
And an example of how to get the "secret" back out (look for |1 secret=
on the first line):
$ docker history f2bcff49ac09
IMAGE CREATED CREATED BY SIZE COMMENT
f2bcff49ac09 8 seconds ago |1 secret=S3CR3T /bin/sh -c echo "${secret}" 0 B
5414c15a1cb6 8 seconds ago /bin/sh -c #(nop) ARG secret 0 B
13e1761bf172 6 months ago /bin/sh -c #(nop) ADD file:614a9122187935fccf 4.797 MB
This is the case if you have built the image locally or pulled it from a registry.
If your goal is to keep the build-time secret out of the running container then using ARG does help you - consider this:
$ docker run --rm -ti f2bcff49ac09 sh
/ # env
HOSTNAME=7bc772fd0f56
SHLVL=1
HOME=/root
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
$ # Note no secret in the above output