I’m experimenting with new HEREDOC syntax in Dockerfile. There is example in official docs that I assume is running some heredoc as script in bash:
# syntax=docker/dockerfile:1
FROM debian
RUN <<EOT bash
apt-get update
apt-get install -y vim
EOT
when I build image like that it seems to work
$ docker buildx build --file ./.docker/Dockerfile-test --no-cache --progress=plain --secret id=composer-auth,src=$(pwd)/auth.json --tag heredoc:test .
#1 [internal] load build definition from Dockerfile-test
#1 transferring dockerfile: 34B
#1 transferring dockerfile: 36B done
#1 DONE 0.0s
......
#8 [1/2] FROM docker.io/library/debian@sha256:534da5794e770279c889daa891f46f5a530b0c5de8bfbc5e40394a0164d9fa87
#8 CACHED
#9 [2/2] RUN <<EOT bash
#9 0.529 Get:1 http://deb.debian.org/debian bullseye InRelease [116 kB]
#9 0.885 Get:2 http://deb.debian.org/debian-security bullseye-security InRelease [48.4 kB]
#9 1.193 Get:3 http://deb.debian.org/debian bullseye-updates InRelease [44.1 kB]
#9 1.294 Get:4 http://deb.debian.org/debian bullseye/main amd64 Packages [8183 kB]
#9 2.110 Get:5 http://deb.debian.org/debian-security bullseye-security/main amd64 Packages [218 kB]
#9 2.134 Get:6 http://deb.debian.org/debian bullseye-updates/main amd64 Packages [14.6 kB]
#9 2.940 Fetched 8624 kB in 3s (3227 kB/s)
#9 2.940 Reading package lists...
#9 3.379 Reading package lists...
#9 3.768 Building dependency tree...
#9 3.881 Reading state information...
#9 4.059 The following additional packages will be installed:
#9 4.059 libgpm2 vim-common vim-runtime xxd
#9 4.061 Suggested packages:
#9 4.061 gpm ctags vim-doc vim-scripts
#9 4.149 The following NEW packages will be installed:
#9 4.149 libgpm2 vim vim-common vim-runtime xxd
#9 4.224 0 upgraded, 5 newly installed, 0 to remove and 0 not upgraded.
#9 4.224 Need to get 8174 kB of archives.
#9 4.224 After this operation, 36.9 MB of additional disk space will be used.
#9 4.224 Get:1 http://deb.debian.org/debian bullseye/main amd64 xxd amd64 2:8.2.2434-3+deb11u1 [192 kB]
#9 4.307 Get:2 http://deb.debian.org/debian bullseye/main amd64 vim-common all 2:8.2.2434-3+deb11u1 [226 kB]
#9 4.329 Get:3 http://deb.debian.org/debian bullseye/main amd64 libgpm2 amd64 1.20.7-8 [35.6 kB]
#9 4.330 Get:4 http://deb.debian.org/debian bullseye/main amd64 vim-runtime all 2:8.2.2434-3+deb11u1 [6226 kB]
#9 4.583 Get:5 http://deb.debian.org/debian bullseye/main amd64 vim amd64 2:8.2.2434-3+deb11u1 [1494 kB]
#9 4.784 debconf: delaying package configuration, since apt-utils is not installed
#9 4.822 Fetched 8174 kB in 0s (16.7 MB/s)
#9 4.838 Selecting previously unselected package xxd.
(Reading database ... 6661 files and directories currently installed.)
#9 4.848 Preparing to unpack .../xxd_2%3a8.2.2434-3+deb11u1_amd64.deb ...
#9 4.850 Unpacking xxd (2:8.2.2434-3+deb11u1) ...
#9 4.885 Selecting previously unselected package vim-common.
#9 4.886 Preparing to unpack .../vim-common_2%3a8.2.2434-3+deb11u1_all.deb ...
#9 4.892 Unpacking vim-common (2:8.2.2434-3+deb11u1) ...
#9 4.922 Selecting previously unselected package libgpm2:amd64.
#9 4.923 Preparing to unpack .../libgpm2_1.20.7-8_amd64.deb ...
#9 4.926 Unpacking libgpm2:amd64 (1.20.7-8) ...
#9 4.948 Selecting previously unselected package vim-runtime.
#9 4.949 Preparing to unpack .../vim-runtime_2%3a8.2.2434-3+deb11u1_all.deb ...
#9 4.953 Adding 'diversion of /usr/share/vim/vim82/doc/help.txt to /usr/share/vim/vim82/doc/help.txt.vim-tiny by vim-runtime'
#9 4.957 Adding 'diversion of /usr/share/vim/vim82/doc/tags to /usr/share/vim/vim82/doc/tags.vim-tiny by vim-runtime'
#9 4.958 Unpacking vim-runtime (2:8.2.2434-3+deb11u1) ...
#9 5.467 Selecting previously unselected package vim.
#9 5.468 Preparing to unpack .../vim_2%3a8.2.2434-3+deb11u1_amd64.deb ...
#9 5.473 Unpacking vim (2:8.2.2434-3+deb11u1) ...
#9 5.573 Setting up libgpm2:amd64 (1.20.7-8) ...
#9 5.578 Setting up xxd (2:8.2.2434-3+deb11u1) ...
#9 5.583 Setting up vim-common (2:8.2.2434-3+deb11u1) ...
#9 5.593 Setting up vim-runtime (2:8.2.2434-3+deb11u1) ...
#9 5.640 Setting up vim (2:8.2.2434-3+deb11u1) ...
#9 5.644 update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vim (vim) in auto mode
#9 5.646 update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vimdiff (vimdiff) in auto mode
#9 5.648 update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/rvim (rvim) in auto mode
#9 5.650 update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/rview (rview) in auto mode
#9 5.652 update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/vi (vi) in auto mode
#9 5.655 update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/view (view) in auto mode
#9 5.657 update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/ex (ex) in auto mode
#9 5.660 update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/editor (editor) in auto mode
#9 5.667 Processing triggers for libc-bin (2.31-13+deb11u5) ...
#9 DONE 5.7s
#10 exporting to image
#10 exporting layers
#10 exporting layers 0.4s done
#10 writing image sha256:bc054c50e052f8413c89a458d7bdab80529d86449c52f9b590a5289e3ea97308 done
#10 naming to docker.io/library/heredoc:test done
#10 DONE 0.4s
But this is actually run by /bin/sh
not bash
because when I use bash features like this:
# syntax=docker/dockerfile:1
FROM debian
RUN <<EOT bash
to_install=(
vim
)
apt-get update
apt-get install -y "${to_install[@]}"
EOT
I get this error:
$ docker buildx build --file ./.docker/Dockerfile-test --no-cache --progress=plain --secret id=composer-auth,src=$(pwd)/auth.json --tag heredoc:test .
#1 [internal] load build definition from Dockerfile-test
#1 transferring dockerfile:
#1 transferring dockerfile: 188B done
#1 DONE 0.0s
......
#8 [1/2] FROM docker.io/library/debian@sha256:534da5794e770279c889daa891f46f5a530b0c5de8bfbc5e40394a0164d9fa87
#8 CACHED
#9 [2/2] RUN <<EOT bash
#9 0.268 /bin/sh: 1: Bad substitution
#9 ERROR: executor failed running [/bin/sh -c <<EOT bash
to_install=(
vim
)
apt-get update
apt-get install -y "${to_install[@]}"
EOT]: exit code: 2
------
> [2/2] RUN <<EOT bash:
#9 0.268 /bin/sh: 1: Bad substitution
------
error: failed to solve: executor failed running [/bin/sh -c <<EOT bash
to_install=(
vim
)
apt-get update
apt-get install -y "${to_install[@]}"
EOT]: exit code: 2
I also tried using #!/bin/bash -ce
at the beginning of heredoc string but it still was using /bin/sh
. Only changing shell in dockerfile like:
SHELL ["/bin/bash", "-ce"]
works as expected.
Is this example misleading or I’m doing something wrong that bash does not work for me with example from official docs?
2
Answers
The issue is that the
$
is being evaluated in thesh
shell which is running theEOT
command. Escaping it resolves the issue:Please put
set -eu
at the beginning of the heredoc.Else builds can succeed when they must fail.
set -e
orset --errexit
= If any command fail the script will exit with non-zero valueset -u
orset --nounset
= If a variable is unset it will exit with a non zero statusset -x
orset --xtrace
= Useful for debugging, print+
and the executed command.