I was playing around and got stuck while trying to capture the exit code of a script I'm running within a heredoc in a Docker container.

Say I want to run this command to start a Docker container loaded with python:3.7, and execute a heredoc inside of it.

docker run -v $PWD:/workspace -w /workspace --rm -i python:3.7 <<-EOF
    echo $?

Suppose script.sh looks like this:

echo 'Before'
exit 1
echo 'After'

When I run that, I don't get


like I expected, but rather


When I try to assign the exit code to a variable like

echo $code

I get this:


How can I reliably capture the exit code of script.sh which is run within a heredoc?

I imagine it has something to do with it running in a heredoc in the first place, as running that same sequence of commands within the container directly works fine.

1 Answer 1


Your here-document is not quoted, which means that the invoking shell will expand variables within it before passing it to docker.

Two solutions:

  1. Quote the here-document by quoting any part of the initial here-document delimiter:

    docker ... <<-'MY_SCRIPT'
        echo "$?"

    Any variant of 'MY_SCRIPT', "MY_SCRIPT", or \MY_SCRIPT would work (even 'MY'_SCRIPT etc.) The actual delimiter should be a word and is usually written in upper-case. I've used a word that additionally describes the redirected document as a way of documenting the code.

  2. Escape the $ character within the redirected document to stop the shell from expanding that particular variable:

    docker ... <<-MY_SCRIPT
        echo "\$?"

    This alternative solution is often used when the here-document contains a combination of variables that need to be expanded by the invoking shell and others that need to be passed as is.


This site is temporarily in read-only mode and not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .