Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mounting secret as environment variable does not behave as expected. #5439

Closed
steve-th247 opened this issue Oct 20, 2024 · 5 comments
Closed

Comments

@steve-th247
Copy link

steve-th247 commented Oct 20, 2024

Building an image with the dockerfile below, /test.txt in the image contains the secret as expected. when the secret source is a file. Using environment variable as source does not work (#3787).

FROM alpine:3.19
 
RUN --mount=type=secret,id=test-secret,env=TESTVAR \
        echo $TESTVAR > /test.txt
 
ENTRYPOINT ["sh", "-c"]

However, the file becomes empty if the RUN instruction gets modified to any of the following:

RUN --mount=type=secret,id=test-secret,env=TESTVAR \
        echo "$TESTVAR" > /test.txt
RUN --mount=type=secret,id=test-secret,env=TESTVAR \
        echo -e $TESTVAR > /test.txt
RUN --mount=type=secret,id=test-secret,env=TESTVAR \
        echo $TESTVAR > /test.txt \
	&& echo foo > /test2.txt
RUN --mount=type=secret,id=test-secret,env=TESTVAR \
	TESTVAR1=$TESTVAR \
        && echo $TESTVAR1 > /test.txt

The following RUN instruction behaves as expected, resulting in the creation of file /test2.txt containing the string "test2".

RUN --mount=type=tmpfs,target=/tmpdir,size=1M \
        TESTVAR=test2 \
        && echo "$TESTVAR" > /test2.txt \
        && echo test1212

Output of docker info

Client: Docker Engine - Community
 Version:    27.3.1
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.17.1
    Path:     /usr/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.29.7
    Path:     /usr/libexec/docker/cli-plugins/docker-compose
 
Server:
 Containers: 0
  Running: 0
  Paused: 0
  Stopped: 0
 Images: 1
 Server Version: 27.3.1
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Using metacopy: false
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 7f7fdf5fed64eb6a7caf99b3e12efcf9d60e311c
 runc version: v1.1.14-0-g2c9f560
 init version: de40ad0
 Security Options:
  apparmor
  seccomp
   Profile: builtin
  cgroupns
 Kernel Version: 6.1.0-26-amd64
 Operating System: Debian GNU/Linux 12 (bookworm)
 OSType: linux
 Architecture: x86_64
 CPUs: 4
 Total Memory: 3.823GiB
 Name: debian12-docker
 ID: 69675a88-2cbd-41ee-a58a-d4214b79df7e
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false
 
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled

Output of docker buildx inspect

Name:          default
Driver:        docker
Last Activity: 2024-10-20 19:20:22 +0000 UTC
 
Nodes:
Name:             default
Endpoint:         default
Status:           running
BuildKit version: v0.16.0
Platforms:        linux/amd64, linux/amd64/v2, linux/386
Labels:
 org.mobyproject.buildkit.worker.moby.host-gateway-ip: 172.17.0.1
@thaJeztah
Copy link
Member

I double checked, and mounting the secret as an env-var was added in this PR; Which is indeed part of BuildKit 0.16 (default builder in Docker 27.3).

However, I was not able to reproduce your issue

test 1

# syntax=docker/dockerfile:1

FROM alpine

RUN --mount=type=secret,id=test-secret,env=TESTVAR \
        echo "$TESTVAR" > /test.txt \
export test1="testing 123"

docker build --secret id=test-secret,env=test1 --no-cache -t foo .

docker run --rm foo cat /test.txt
testing 123

test 2

# syntax=docker/dockerfile:1

FROM alpine

RUN --mount=type=secret,id=test-secret,env=TESTVAR \
        echo -e $TESTVAR > /test.txt
export test1="testing 234"

docker build --secret id=test-secret,env=test1 --no-cache -t foo .

docker run --rm foo cat /test.txt
testing 234

test 3

# syntax=docker/dockerfile:1

FROM alpine

RUN --mount=type=secret,id=test-secret,env=TESTVAR \
    echo $TESTVAR > /test.txt \
    && echo foo > /test2.txt \
export test1="testing 345"

docker build --secret id=test-secret,env=test1 --no-cache -t foo .

docker run --rm foo cat /test.txt
testing 345

docker run --rm foo cat /test2.txt
foo

test 4

# syntax=docker/dockerfile:1

FROM alpine

RUN --mount=type=secret,id=test-secret,env=TESTVAR \
	TESTVAR1=$TESTVAR \
        && echo $TESTVAR1 > /test.txt
export test1="testing 456"

docker build --secret id=test-secret,env=test1 --no-cache -t foo .

docker run --rm foo cat /test.txt
testing 456

@thaJeztah
Copy link
Member

Silly question; are you perhaps using sudo to run your docker build? Because in that case it may be that that's the culprit. sudo by default does NOT inherit environment variables from your current environment;

export test1="without sudo"
docker build --secret id=test-secret,env=test1 --no-cache -t foo .
docker run --rm foo cat /test.txt
without sudo

export test1="with sudo"

sudo docker build --secret id=test-secret,env=test1 --no-cache -t foo .
docker run --rm foo cat /test.txt

However using sudo -E (-E preserves the current environment variables);

sudo -E docker build --secret id=test-secret,env=test1 --no-cache -t foo .
docker run --rm foo cat /test.txt
with sudo

@steve-th247
Copy link
Author

steve-th247 commented Oct 20, 2024

That's not a silly question at all, but I wasn't using sudo. I tested again, and the behaviour persisted.
I spun up another VM just for a test with the same ISO, and it is now behaving as expected in the new VM. So I guess it is something else in my environment, but I currently have no idea about what it might be.
I can confirm that everything works as expected in the fresh installation though. Thank you very much for your help. I'm closing this.

@steve-th247 steve-th247 closed this as not planned Won't fix, can't repro, duplicate, stale Oct 20, 2024
@thaJeztah
Copy link
Member

Glad to hear it's working now! I thought I'd mention the sudo situation, because I've seen many people, myself included (and recently a colleague) running into that, and not everyone is aware of that behaviour 😂

One thing worth mentioning is that Dockerfile features are implemented in the Dockerfile "front-end" ("parser"). BuildKit ships with a default version of that parser which is compiled in, but will be the version that shipped with the version of Buildkit (or Docker Engine) that's installed.

However, the parser can be updated independently of BuildKit. This may help in situations where you run a build in multiple environments, and not all of those may be running "latest"; if you add syntax directive at the start of your Dockerfile, then BuildKit will pull the given syntax before running your build; e.g. the docker/dockerfile:1 syntax will always pull the latest stable syntax;

# syntax=docker/dockerfile:1

Also see https://www.bretfisher.com/dockerfile-frontends/

@dennisoehme
Copy link

I run into the same situation, sporadically my secret environment variable is not there. Specifically, I use bake to build the images. The problem occurs after I have done the following following:

  • upgrade dockerfile from 1.7 to syntax=docker/dockerfile:1.10
    • upgrade secrets from file to environment variable (see below)
  • upgrade environment from docker:27.0.3-dind-rootless to `docker:27.2.1-dind-rootless'

Old:

RUN --mount=type=secret,id=GITLAB_API_TOKEN <<EOT
    export GITLAB_API_TOKEN=$(cat /run/secrets/GITLAB_API_TOKEN)
...

New

RUN --mount=type=secret,id=GITLAB_API_TOKEN,env=GITLAB_API_TOKEN <<EOT
...

Now sometimes GITLAB_API_TOKEN is empty or not set. Technically, my setup runs as part of a Jenkins build job in a Kubernetes pod, so not easy to debug when this happens (pod is already gone). I could not reproduce this problem at the moment. But I also had the same problem locally. When I have a little more time, I will try to isolate the problem and provide more details.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants