Command exists via "docker run" but not "docker build"?

Viewed 30

I'm trying to build an image. My issue is that commands that are available via:

docker run -it some-image

are missing when I try to "docker build" starting from some-image.

I have a recipe that I use a lot successfully. In my Dockerfile I like to always use a working directory with my username so I can be sure no other scripts or installations will put files in my working area. I copy the files from the host directory into the image's working directory.

Dockerfile:

FROM some-image
WORKDIR /dimfish
ADD . /dimfish
RUN ./dimfish/tasks-in-container.sh

Then I put the interesting steps to build the image in a shell script. This one isn't really building anything, but it will show that (1) docker is executing this script because the echo lines come through, but (2) the conda command is not found.

tasks-in-container.sh

#!/bin/bash
echo start >&2
which conda >&2
conda
echo end >&2

Finally, I use a script on the host to build the image.

build-image.sh

#!/bin/bash
docker build --progress=plain -t new-image .

This little recipe works for me in many previous instances. But I'm having an issue here where I've searched and run down every reference I can think of to read, and can't understand what the difference is.

As I mentioned at the top, if I do this, the conda command is there as expected:

docker run -it some-image

(base) root@e66e21746ef0:/dimfish# which conda
/root/miniconda3/bin/conda
(base) root@e66e21746ef0:/dimfish# conda
usage: conda [-h] [-V] command ...
   ...

But when I try to build, I can see the other steps of my script executing, and we're starting from the same image, and yet the conda command is not found:

./build-image.sh

start
/dimfish/tasks-in-container.sh: line 4: conda: command not found
end

Any idea what's different here that I'm not considering?

1 Answers

David Maze's comment led to the answer. It seems I haven't run into this with docker before because often the build scripts are doing a lot of "apt-get install xyz" and the installed commands are not sensitive to this problem.

Conda in particular, but other installation steps could do this, added a block to /root/.bashrc when it was installed. The problem is that the top of this file has a branch to exit early if it decides the execution is not an interactive shell.

/root/.bashrc in the base some-image of our example:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

...snip...

# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/root/miniconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    if [ -f "/root/miniconda3/etc/profile.d/conda.sh" ]; then
        . "/root/miniconda3/etc/profile.d/conda.sh"
    else
        export PATH="/root/miniconda3/bin:$PATH"
    fi
fi
unset __conda_setup
# <<< conda initialize <<<

So I added some commands to tasks-in-container.sh:

#!/bin/bash

# The path for conda is in root's .bashrc, but root's .bashrc
# exits early if we're "not in interactive shell", so set the
# prompt to something non-empty.
PS1=">"
source /root/.bashrc

With the prompt set, and the .bashrc re-sourced, the rest of the script is able to find the conda command.

Related