skip to Main Content

I have a Dockerfile in which I am trying to install and use asdf to manage Python package versions. A snippet of my Dockerfile appears below.


SHELL ["/bin/bash", "-c"] 

RUN git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.10.0
RUN chmod +x ~/.asdf/asdf.sh ~/.asdf/completions/asdf.bash
RUN echo ". $HOME/.asdf/asdf.sh" >> ~/.bashrc
RUN echo ". $HOME/.asdf/completions/asdf.bash" >> ~/.bashrc
ENV PATH="$HOME/.asdf/bin:$HOME/.asdf/shims:$PATH"
ENV PATH="$HOME/.asdf:$PATH"
RUN echo -e 'nsource $HOME/.asdf/asdf.sh' >> ~/.bashrc
RUN source ~/.bashrc
RUN bash -c 'echo -e which asdf'
RUN asdf plugin-add python

That last line is the offending line. When I try to build this Docker image, I get the following.

 => ERROR [17/19] RUN asdf plugin-add python                                                                                                                    0.3s
------
 > [17/19] RUN asdf plugin-add python:
#21 0.292 /bin/bash: asdf: command not found
------
executor failed running [/bin/bash -c asdf plugin-add python]: exit code: 127

However, if I remove that line, I’m able to run a container and then just immediately run asdf successfully.

docker run -it <image ID>
root:# asdf plugin-add python
initializing plugin repository...Cloning into '/root/.asdf/repository'...
<etc>

Why doesn’t this work when I try to run it through the Dockerfile?

2

Answers


  1. This…

    RUN source ~/.bashrc
    

    Does absolutely nothing. Each RUN command executes in a new shell, which exits when the command completes. Sourcing bash scripts, setting variables, and other things that modify the current environment will not persist to subsequent RUN commands.

    You could modify your Dockerfile to run a sequence of commands in a RUN command, like this:

    RUN source ~/.bashrc; 
      asdf plugin-add python
    

    …which would at least successfullly source the .bashrc file and presumably make the asdf tool available.

    Login or Signup to reply.
  2. I found that source ~/.bashrc; just doesn’t always do it in a docker container (it doesn’t in a live OS at times), nor does /bin/bash -c 'source ~/.bashrc';.

    The trick to installing asdf in a Docker container at build time, I found, was to go as far as to restart bash (i.e. exec bash). Possibly it has to do with the fact that we’re not actually modifying something like PATH= and subsequently source <file>‘ing it, but using posix compliant source directives to alias an executable script by the filename (minus its extension).

    . $HOME/.asdf/asdf.sh

    Means:

    source /home/user/.asdf/asdf.sh

    Which seemingly gives the effect of:

    alias asdf=/home/user/.asdf/asdf.sh

    Simply sourcing the file won’t work because the install instructions (provided by asdf authors) provide essentially a source directive to place inside of ~/.bashrc, and I believe the context then becomes one other than the one the shell we’re using is subsequently under.

    To fix this, we have to restart bash – there’s no other way.

    We’ll also run into a lot of quirks and issues we have to circumvent when trying to configure user packages (just semantics, really) as root, so to avoid that its best to establish a non-root user to work with.

    Here’s a working example that goes further to install Ruby and NodeJS:

    FROM debian:bookworm-slim
    # .. LABEL, etc., ...
    #
    RUN apt-get update && 
    # prep tools also for asdf (last 2)
        apt-get install -y curl git 
            software-properties-common 
            gnupg2 apt-transport-https 
    # prep deps for asdf-ruby
            build-essential autoconf 
            bison patch rustc 
            libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libgmp-dev 
            libncurses5-dev libffi-dev libgdbm6 libgdbm-dev libdb-dev uuid-dev 
    # prep deps for asdf-nodejs
            dirmngr gawk 
    # prep deps for non-root user
            sudo; 
    # create special user
        useradd --create-home --shell /bin/bash gitlab; 
        /bin/bash -c 'echo "gitlab:password" | chpasswd'; 
        adduser gitlab sudo
    
    ## change user for all subsequent commands
    USER gitlab
    
    # change working directory
    WORKDIR /home/gitlab
    
    # install asdf
    RUN 
        # configure git to get rid of detached head warnings
        git config --global advice.detachedHead false; 
        git clone https://github.com/asdf-vm/asdf.git $HOME/.asdf --branch v0.10.2; 
        /bin/bash -c 'echo -e "nn## Configure ASDF n. $HOME/.asdf/asdf.sh" >> ~/.bashrc'; 
        /bin/bash -c 'echo -e "nn## ASDF Bash Completion: n. $HOME/.asdf/completions/asdf.bash" >> ~/.bashrc'; 
        exec bash; 
    # install asdf-ruby
        /bin/bash -c asdf plugin add ruby https://github.com/asdf-vm/asdf-ruby.git; 
    # install asdf-nodejs
        /bin/bash -c asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git;
    
    # whatever you now want to do -
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search