Commit 943deb6c authored by Devin OKelly's avatar Devin OKelly
Browse files

Initial commit

This is an example minimal directory for configuring a Vagrant box, using Virtualbox
as the VM provider, which contains Singularity. This allows for building of Singularity
recipes locally to a BioHPC workstation, without relying on Cloud Builder or other remote
Author: Devin O'Kelly,
Last Edit: 2021-09-10
Tested on:
Vagrant (``vagrant --version``) 1.9.1
Virtualbox (``vboxmanage --version``) 5.1.38r122592
BioHPC thin client
Usage instructions are as follows, with more technical detail below that. When possible, it will be noted in which context a command is meant to be executed.
The workstation will be referred to as "host", relative to the vagrant box, which is the "guest". The singularity
container, whether invoked with 'exec', 'run', or 'shell', will be referred to as "Singularity guest".
0. (optional) Check to see if you have any other virtual machines running (in case of port collision) - ``vagrant global-status`` . You may want to manually check for virtualbox or VMware machines as well, if you suspect you'll have those. Vagrant can usually automatically handle port collisions for SSH.
1. Bring up the Vagrant box. Navigate to the folder containing the Vagrantfile (which should be where this README is), and run
``vagrant up`` from your terminal. This could take a while, so if you are running a remote session you may want to run ``vagrant up | tee log.txt`` instead,
just in case the box creation fails or your terminal drops for some reason.
- If you want to run Singularity without having to type out the entire path to the binary at ``/usr/local/bin/singularity/``, add the following to your ``~/.bashrc``:
- ``alias sudo='sudo env PATH=$PATH'``
- Notice that the file ``///provision/`` creates and activates a default venv within the Vagrant box using packages specified in ``requirements.txt``.
2. Once the Vagrant box is up, get into it with ``vagrant ssh``. This will drop you into an SSH shell running within the Vagrant box, as the ``vagrant`` user, which has sudo rights within the VM. Vagrant should also have automatically mounted the host ``"~/vagrant_singularity/"`` folder to the guest ``"/vagrant/"`` folder - if not, there is something wrong with your Virtualbox or Vagrant installs.
3. Within Vagrant, if you navigate to /vagrant/, you should see the /vagrant/recipe/ folder which contains the ``example.def`` recipe file.
* ``sudo singularity build ./output.sif /vagrant/recipe/example.def`` will create a file called ``output.sif`` in the current folder. This is your Singularity guest image file.
* ``sudo singularity build --sandbox ./my_sandbox/ /vagrant/recipe/example.def`` will create a **folder** called ``my_sandbox`` in the current folder. This is a Singularity guest sandbox folder. If you navigate inside, you will see what looks like the root of a filesystem, with multiple directories like /bin/ and /var/.
4. You can run either images or sandbox directories - the difference is that an image is meant to be immutable, and generally to function as a stable application+its environment. Conversely, a sandbox is meant to be mutable.
5. You can convert sandboxes to SIF files, and SIF files to sandboxes, via the build command. If you do this, you may limit reproducibility as Singularity does not track the changes you make within a sandbox in a reproducible manner. As such, it is best to follow the pattern
- Create base definition file
- Create SIF file
- Convert SIF to sandbox
- Within sandbox, figure out what changes need to be made to the image
- Modify or extend the base definition file.
- Create updated SIF file
- repeat.
The Vagrant box functions purely to provide an encapsulated environment where you can have the root permissions needed to build SIF files.
It is expected that once you have a satisfactory Singularity image that you will be able to save that image elsewhere to be shared with others. In the context of having a stable environment, it should then be able to function as the 'engine' via which python and MATLAB scripts are executed.
Once you have developed an application which uses your stable base image, you can then build another container with that application included. This can be accomplished by appending the appropriate build instructions to the definition file, convert a writable sandbox into a static image, or using a From statement in another definition file which points to your base image. For reproducibility, it is generally best to modify a single definition file and rebuild each time, rather than building a sandbox.
vagrant@vagrant :
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
# Centos-7.6 is the matched version of BioHPC's RHEL version and should be the most stable.
# = "bento/centos-7.6"
config.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 4
# Forward guest ports to the host. "forwarded_port", guest: 8000, host: 9000 "forwarded_port", guest: 80, host: 9080
# Install system things as the root user via sudo
config.vm.provision "shell", path: "provision/"
# Install non-system things (this is where you would pip install things)
config.vm.provision "shell", path: "provision/", privileged: false
set -ef -o pipefail
# This script installs a new python and then sets up a virtualenv based on requirements.txt
echo "Virtualenv Setup"
echo "This script will install python and a virtual environment containing all"
echo "dependencies in requirements.txt"
# Where am I?
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
if [ -z $PYTHON_DIR ]; then
if [ -z $VENV_DIR ]; then
# Install Python 3.6.10 and SQLite 3.32.2 from source
echo "Installing Python ${PYTHON_VER}"
if [ ! -d "$PYTHON_DIR" ]; then
mkdir "$PYTHON_DIR"
if [ ! -d "$PYTHON_DIR/src" ]; then
mkdir "$PYTHON_DIR/src"
cd "$PYTHON_DIR/src"
if [ ! -f "$PYTHON_DIR/src/Python-${PYTHON_VER}.tgz" ]; then
wget --quiet${PYTHON_VER}/Python-${PYTHON_VER}.tgz
if [ ! -x "$PYTHON_DIR/bin/python" ]; then
tar -zxf Python-${PYTHON_VER}.tgz
cd Python-${PYTHON_VER}
LD_RUN_PATH=$PYTHON_DIR/lib ./configure LDFLAGS="-L$PYTHON_DIR/lib" CPPFLAGS="-I$PYTHON_DIR/include" --prefix="$PYTHON_DIR" --quiet
LD_RUN_PATH=$PYTHON_DIR/lib make -j4 --quiet
make install --quiet
# Install pip
echo "Installing pip"
if [ ! -f "$PYTHON_DIR/src/" ]; then
wget --quiet
# Install virtualenv package
echo "Installing virtualenv to local python"
"$PYTHON_DIR/bin/pip" install --ignore-installed virtualenv
# Create our virtualenv
echo "Creating virtualenv at .venv"
"$PYTHON_DIR/bin/virtualenv" "$VENV_DIR"
echo "export PYTHONPATH=\$PYTHONPATH:$BASE_DIR" >> "$VENV_DIR/bin/activate"
# Activate the virtual env
echo "Activating virtualenv"
. "$VENV_DIR/bin/activate"
# Install basic & dev requirements first
cd "$BASE_DIR"
pip install -r requirements.txt
echo "Removing source files / build tree"
rm -rf "${PYTHON_DIR}/src"
echo "Complete"
# Setup Proxy
if ping -c 1 &> /dev/null; then
echo "export http_proxy=" > /etc/profile.d/
echo "export https_proxy=" >> /etc/profile.d/
echo "export all_proxy=" >> /etc/profile.d/
. /etc/profile.d/
echo "proxy=" >> /etc/yum.conf
# Enable EPEL
yum -y install epel-release
# Install build packages
#echo yum "Installing packages for build"
#yum -y groupinstall "Development Tools" "Development Libraries"
#yum -y install readline-devel zlib-devel openssl-devel sqlite-devel bzip2-devel mysql-devel openldap-devel libjpeg-turbo-devel libgit2-devel cmake libffi-devel
yum update -y && \
yum groupinstall -y 'Development Tools' && \
yum install -y \
openssl-devel \
libuuid-devel \
libseccomp-devel \
wget \
# Install Go
export VERSION=1.13
export OS=linux
export ARCH=amd64
wget --quiet$VERSION.$OS-$ARCH.tar.gz && \
tar -C /usr/local -xzf go$VERSION.$OS-$ARCH.tar.gz && \
rm go$VERSION.$OS-$ARCH.tar.gz
echo 'export PATH=/usr/local/go/bin:$PATH' >> ~/.bashrc && \
source ~/.bashrc
echo 'export PATH=/usr/local/go/bin:$PATH' >> /etc/profile
# Install Singularity
export VERSION=3.5.3
wget --quiet${VERSION}/singularity-${VERSION}.tar.gz && \
tar -xzf singularity-${VERSION}.tar.gz &&
rm singularity-${VERSION}.tar.gz && \
cd ./singularity
./mconfig && \
make -C builddir && \
make -C builddir install
echo 'export PATH=/usr/local/bin/singularity:$PATH' >> /etc/profile
echo 'alias sudo=\'sudo env PATH=$PATH\'' >> ~/.bashrc
# Install python and deps
cd /vagrant
export PYTHON_DIR="$HOME/python"
export VENV_DIR="$HOME/venv"
export PYTHON_VER="3.6.10"
# Note that this is now being executed within the vagrant environment.
. $HOME/venv/bin/activate
echo '. ~/venv/bin/activate' >> ~/.bash_profile
echo 'export PYTHONPATH="$PYTHONPATH:/vagrant"' >> ~/.bash_profile
BootStrap: library
From: ubuntu:16.04
apt-get -y update
apt-get -y install fortune cowsay lolcat
export LC_ALL=C
export PATH=/usr/games:$PATH
fortune | cowsay | lolcat
Author GodloveD
# Requirements for internal virtualenv
# YAML metadata
# Documentation generation
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment