moby / buildkit

concurrent, cache-efficient, and Dockerfile-agnostic builder toolkit
https://github.com/moby/moby/issues/34227
Apache License 2.0
8.11k stars 1.14k forks source link

shebang not respected using heredoc with tabs stripped #5383

Open rubensa opened 1 week ago

rubensa commented 1 week ago

Looks like shebang is not respected on RUN command if you have a heredoc with tabs stripped

If I have (heredoc without tab strip):

Dockerfile.ok

# syntax=docker/dockerfile:1.4
FROM bash
RUN <<EOT
#!/usr/bin/env bash
ps | grep $$
EOT

I can run:

docker buildx build -f Dockerfile.ok --no-cache .

And I get something like:

#0 building with "default" instance using docker driver

#1 [internal] load build definition from Dockerfile.ok
#1 transferring dockerfile: 128B done
#1 DONE 0.0s

#2 [internal] load .dockerignore
#2 transferring context: 2B done
#2 DONE 0.0s

#3 resolve image config for docker.io/docker/dockerfile:1.4
#3 DONE 0.5s

#4 docker-image://docker.io/docker/dockerfile:1.4@sha256:9ba7531bd80fb0a858632727cf7a112fbfd19b17e94c4e84ced81e24ef1a0dbc
#4 CACHED

#5 [internal] load metadata for docker.io/library/bash:latest
#5 DONE 0.5s

#6 [1/2] FROM docker.io/library/bash@sha256:ce062497c248eb1cf4d32927f8c1780cce158d3ed0658c586a5be7308d583cbb
#6 CACHED

#7 [internal] preparing inline document
#7 CACHED

#8 [2/2] RUN <<EOT (#!/usr/bin/env bash...)
#8 0.151     1 root      0:00 bash /dev/pipes/EOT
#8 0.151     8 root      0:00 grep 1
#8 DONE 0.2s

#9 exporting to image
#9 exporting layers 0.1s done
#9 writing image sha256:fef2554f3b9106230c8fe1796087e4ada1c63fb3cf516eb4680678de5e816794 done
#9 DONE 0.1s

Where you can see in 1 root 0:00 bash /dev/pipes/EOT output that the shell used is bash.

On the other hand, If I have (heredoc with tab strip):

Dockerfile.ko

# syntax=docker/dockerfile:1.4
FROM bash
RUN <<-EOT
    #!/usr/bin/env bash
    ps | grep $$
EOT

I can run:

docker buildx build -f Dockerfile.ko --no-cache .

And I get something like:

#0 building with "default" instance using docker driver

#1 [internal] load build definition from Dockerfile.ko
#1 transferring dockerfile: 228B done
#1 DONE 0.0s

#2 [internal] load .dockerignore
#2 transferring context: 2B done
#2 DONE 0.0s

#3 [auth] docker/dockerfile:pull token for registry-1.docker.io
#3 DONE 0.0s

#4 resolve image config for docker.io/docker/dockerfile:1.4
#4 DONE 1.1s

#5 docker-image://docker.io/docker/dockerfile:1.4@sha256:9ba7531bd80fb0a858632727cf7a112fbfd19b17e94c4e84ced81e24ef1a0dbc
#5 CACHED

#6 [auth] library/bash:pull token for registry-1.docker.io
#6 DONE 0.0s

#7 [internal] load metadata for docker.io/library/bash:latest
#7 DONE 1.0s

#8 [1/2] FROM docker.io/library/bash@sha256:ce062497c248eb1cf4d32927f8c1780cce158d3ed0658c586a5be7308d583cbb
#8 CACHED

#9 [2/2] RUN <<-EOT (#!/usr/bin/env bash...)
#9 0.146     1 root      0:00 /bin/sh -c #!/usr/bin/env bash ps | grep $$ 
#9 0.146     8 root      0:00 grep 1
#9 DONE 0.2s

#10 exporting to image
#10 exporting layers 0.1s done
#10 writing image sha256:3131df0782a800571aced5d594ed84c64b53ba3a7de69649c78d650d20128236 done
#10 DONE 0.1s

Where you can see in 1 root 0:00 /bin/sh -c #!/usr/bin/env bash ps | grep $$ output that the shell used is /bin/sh (not bash, as specified in the shebang #!/usr/bin/env bash).

As a side note, I also checked that the heredoc tab strip is really done so it looks like the issue is that the shebang is checked before the heredoc tab strip is done.

tonistiigi commented 5 days ago

@jedevc