docker run interactive with conda environment already activated

Viewed 943

I'd like to create a docker image such that when you run it interactively, a conda environment is already activated.

Current state:

docker run -it my_image
(base) root@1c32ba066db2:~# conda activate my_env
(my_env) root@1c32ba066db2:~#

Desired state:

docker run -it my_image
(my_env) root@1c32ba066db2:~#

More info:

In my Dockerfile, I include all the necessary RUN commands to install conda, create the environment, and activate the environment. Relevant portions reproduced below.

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

...

# Install miniconda.
ENV CONDA_DIR $HOME/miniconda3
RUN wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh && \
    chmod +x ~/miniconda.sh && \
    ~/miniconda.sh -b -p $CONDA_DIR && \
    rm ~/miniconda.sh
# Make non-activate conda commands available.
ENV PATH=$CONDA_DIR/bin:$PATH
# Make conda activate command available from /bin/bash --login shells.
RUN echo ". $CONDA_DIR/etc/profile.d/conda.sh" >> ~/.profile
# Make conda activate command available from /bin/bash --interative shells.
RUN conda init bash

# Create and activate the environment.
RUN conda env create --force -f environment.yml
RUN conda activate my_env

When I run this, conda activate my_env seems to run and succeed. But when I enter interactively with docker run -it, the activated env is (base).

Additionally, I've tried having the last command be CMD conda activate my_env, but then it just runs that and does not enter interactive mode.

2 Answers

Each RUN statement (including docker run) is executed in a new shell, so one cannot simply activate an environment in a RUN command and expect it to continue being active in subsequent RUN commands.

Instead, you need to activate the environment as part of the shell initialization. The SHELL command has already been changed to include --login, which is great. Now you simply need to add conda activate my_env to .profile or .bashrc:

...
# Create and activate the environment.
RUN conda env create --force -f environment.yml
RUN echo "conda activate my_env" >> ~/.profile

and just be sure this is after the section added by Conda.

The following code in my Dockerfile does what you describe:

# Install anaconda
RUN cd $HOME && wget https://repo.anaconda.com/miniconda/Miniconda3-py38_4.10.3-Linux-x86_64.sh && bash Miniconda3-py38_4.10.3-Linux-x86_64.sh -b -p $HOME/miniconda
# Create env
RUN $HOME/miniconda/bin/conda init bash
RUN $HOME/miniconda/bin/conda env create -f my_env.yml
# Activate conda environment on startup
RUN echo "export PATH=$HOME/miniconda/bin:$PATH" >> $HOME/.bashrc
RUN echo "conda init bash" >> $HOME/.bashrc
RUN echo "conda activate my_env" >> $HOME/.bashrc
SHELL ["/bin/bash"]

results in:

(my_env) root@e5fe69843fa1:/# 

when running an interactive container.

Remember to change all instances of my_env to the name of your conda environment.

Related