skip to Main Content

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


  1. The issue is that the $ is being evaluated in the sh shell which is running the EOT command. Escaping it resolves the issue:

    RUN <<EOT bash
      to_install=(
        vim
      )
      apt-get update
      apt-get install -y "${to_install[@]}"
    EOT
    
    Login or Signup to reply.
  2. Please put set -eu at the beginning of the heredoc.

    Else builds can succeed when they must fail.

    FROM debian
    RUN <<EOT bash
      set -eux
      to_install=(
        vim
      )
      apt-get update
      failing_command # set -e exit with non-zero status 
      apt-get install -y "${to_install[@]}"
    EOT
    

    set -e or set --errexit = If any command fail the script will exit with non-zero value
    set -u or set --nounset = If a variable is unset it will exit with a non zero status
    set -x or set --xtrace = Useful for debugging, print + and the executed command.
    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search