15

I've come across several instances where it would be really helpful to containerize a conda environment for long-term reproducibility. As I'm normally running in high-performance computing systems, they need to be Singularity containers for security reasons. How can this be done?

LucasBoatwright
  • 1,456
  • 1
  • 16
  • 20

3 Answers3

24

First, you'll want to get the environment YML for your particular conda environment.

conda activate your_env
conda env export > environment.yml

Here's an example Singularity recipe (in file named 'Singularity' in same directory as 'environment.yml'):

Bootstrap: docker

From: continuumio/miniconda3

%files
    environment.yml

%post
    /opt/conda/bin/conda env create -f environment.yml

%runscript
    exec /opt/conda/envs/$(head -n 1 environment.yml | cut -f 2 -d ' ')/bin/"$@"

Build this with

sudo singularity build conda.sif Singularity

Now, you'll have a functioning container using libraries from your conda environment that can be run anywhere you have Singularity installed!

Example:

singularity run conda.sif ipython

Notes:

Depending on the version of Singularity you're using, you may need to alter $(head -n 1 environment.yml | cut -f 2 -d ' ') with the name of your environment.

Since you can't activate the environment from the runscript, you'll be restricted to binaries installed in your particular environment with the provided runscript.

LucasBoatwright
  • 1,456
  • 1
  • 16
  • 20
  • I tried and after the "run" I get this error: `singularity run conda.simg conda -h` `head: cannot open 'env.yaml' for reading: No such file or directory` – Andrea T. Dec 19 '19 at 17:08
  • @AndreaT. It's an issue with the echo "source activate $(...)" > ~/.bashrc command not being executed properly. You could hard code the result of the head/cut command and retry. – LucasBoatwright Dec 19 '19 at 20:15
  • @compBio Thank you, this works decently if I have root access. Any idea whether there is a workaround if I am only a local user? – ATpoint Apr 17 '21 at 12:49
  • @ATpoint Singularity has a 'fakeroot' feature that may solve your issue. Though, I'm not as familiar with that. Ex. 'singularity build --fakeroot /tmp/test.sif /tmp/test.def' – LucasBoatwright Apr 19 '21 at 13:06
  • @LucasBoatwright Thanks for your helpful answer. But I have a problem with running conda env in the container. I commanded `singularity shell conda.sif | conda activate my_env` and got error `CommandNotFoundError: Your shell has not been properly configured to use 'conda activate'`. Do you have any clue about this? – Rossy Clair May 22 '23 at 03:39
  • 2
    @RossyClair Did you also try running 'source activate my_env'? The commands required for running 'conda activate my_env' don't get added to the ~/.bashrc when running the above (see 'conda init'). And they can't be added after the fact since the container is read-only. – LucasBoatwright May 22 '23 at 12:37
5

I have found it useful because you can have a container with anaconda3 environment installed and easily create new Environments for your different projects whenever you want.

This is simple and I will go over it step by step:

  1. Create the container in your local machine by the following definition file (you can name it whatever you want. Note that some lines might be avoidable ):

    Bootstrap: library
    From: ubuntu:18.04
    Stage: build
    
    %post
    
    apt-get update && apt-get -y upgrade
    apt-get -y install \
    build-essential \
    wget \
    bzip2 \
    ca-certificates \
    libglib2.0-0 \
    libxext6 \
    libsm6 \
    libxrender1 \
    git
    rm -rf /var/lib/apt/lists/*
    apt-get clean
    #Installing Anaconda 3 
    wget -c https://repo.anaconda.com/archive/Anaconda3-2020.02-Linux-x86_64.sh
    /bin/bash Anaconda3-2020.02-Linux-x86_64.sh -bfp /usr/local
    #Conda configuration of channels from .condarc file
    conda config --file /.condarc --add channels defaults
    conda config --file /.condarc --add channels conda-forge
    conda update conda
    #List installed environments
    conda list
    
  2. Then, in order to build the container, run the following commands:

    sudo singularity build ContainerName.sif YourDefineFile.def
    
  3. Now you can create your conda env(you can use common ways or create it by YML file which is an exported file from an existing environment)

    For example, I did it with a YML file: First, you need to get into your .sif container as following:

     Singularity shell YourContainerName.sif 
    

    And then:

     conda env create --name envname --file=YourEnvironments.yml
    
  4. Therefore, After your env is created, you can activate it with the following commands(again first you need to jump into your container):

    singularity shell YourContainer.Sif
    
    source activate YourEnvName
    
Mohammad
  • 339
  • 3
  • 6
4

Using conda-pack it is possible to containerize existing conda environments without re-creating them from environment.yml. This is particularly useful when the environment doesn't resolve anymore, or when packages have been installed into the environment without conda, e.g. using R's install.packages.

  1. pack the environment

    conda-pack -n <MY_ENV> -o packed_environment.tar.gz
    
  2. create this Singularity file

    
    Bootstrap: docker
    
    From: continuumio/miniconda3
    
    %files
        packed_environment.tar.gz /packed_environment.tar.gz
    
    %post
        tar xvzf /packed_environment.tar.gz -C /opt/conda
        conda-unpack
        rm /packed_environment.tar.gz
    
  3. build the image

    singularity build --fakeroot <OUTPUT_CONTAINER.sif> Singularity
    

For more details, including a Docker/Podman variant, check out my grst/containerize-conda repository.

Limitations: The approach probably only works if the source environment is on a linux x64 machine.

Gregor Sturm
  • 2,792
  • 1
  • 25
  • 34