Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthew Giarra committed Jun 10, 2021
1 parent dbdee6d commit 46bc853
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.DS_Store
*~
64 changes: 64 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# docker2singularity
This script exports a [Docker](https://www.docker.com/) image as a [Singularity](https://sylabs.io/singularity/) `.sif` file. This can be useful for porting Dockerized code to run on shared user systems like clusters, which sometimes run Singularity rather than Docker.

# Prerequisites
- Install Docker (tested with `20.10.6`)

# Usage
1. Build or pull the Docker image you wish to export to a Singularity `.sif` file

```bash
docker pull ubuntu:latest
```

2. Run `docker2sif.sh` to export the image as a `.sif` file

```bash
cd docker2singularity
./docker2singularity.sh ubuntu
```

This should write a file called `ubuntu.sif` in the current working directory, e.g., `docker2singularity/ubuntu.sif`

Optionally, you can specify where to save the output `.sif` file:

```bash
./docker2singularity.sh ubuntu $HOME/ubuntu_singularity.sif
```
#### Expected Output
If it worked, you'll see output similiar to the following:

```bash
Exporting docker image ubuntu --> /Users/giarrmn1/ubuntu_singularity.sif

Image Format: squashfs
Docker Image: ubuntu
Container Name: ubuntu_singularity.sif

Inspected Size: 73 MB

(1/10) Creating a build sandbox...
(2/10) Exporting filesystem...
(3/10) Creating labels...
(4/10) Adding run script...
(5/10) Setting ENV variables...
(6/10) Adding mount points...
(7/10) Fixing permissions...
(8/10) Stopping and removing the container...
(9/10) Building squashfs container...
INFO: Starting build...
INFO: Creating SIF file...
INFO: Build complete: /tmp/ubuntu_singularity.sif
(10/10) Moving the image to the output folder...
27,717,632 100% 80.25MB/s 0:00:00 (xfr#1, to-chk=0/1)
Final Size: 27MB
Exported Docker image ubuntu --> /Users/giarrmn1/ubuntu_singularity.sif

```

#### Help
Run `./docker2singularity -h` to print the help screen, including usage.

# Caveats
- The docker image you wish to export must be available locally, i.e., you need to have built the image before you can export it to `.sif`. There's no reason we couldn't go straight from `Dockerfile` to `.sif` by including the option to `docker build` in the script, but we haven't implemented that yet.

138 changes: 138 additions & 0 deletions docker2singularity.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/bin/bash
# Export Docker image as Singularity .sif file
# Maintainer: Matthew N. Giarra <[email protected]>
# First commit 2021-06-10

# Colors for printing
DIR='\033[95m'
OKBLUE='\033[94m'
OKCYAN='\033[96m'
OKGREEN='\033[92m'
ENDC='\033[0m'
BOLD='\033[1m'
UNDERLINE='\033[4m'
WARNING='\033[93m'
FAIL='\033[91m'

# Color to print on success
SUCCESS=$OKCYAN

# Function to display help
display_help(){
echo -e "$SUCCESS $(basename $0): export docker image as a singularity .sif image file"
echo " Usage: $(basename $0) <docker_image_name>"
echo " Usage: $(basename $0) <docker_image_name> <sif_path_out>"
echo " Example: "
echo " docker pull ubuntu:latest"
echo " ./$(basename $0) ubuntu ubuntu.sif"
echo " Note: run \"docker image ls\" to print available docker images"
echo -e "$ENDC"
exit
}

# Display help if no inputs are supplied
if [ $# -eq 0 ]; then
display_help
fi

# Display help if -h or --h is supplied as the only input
while true; do
case "$1" in
-h | --help)
display_help;;
*)
break;;
esac
done

# Tag of the docker image to export as Singularity .sif file
IMAGE_NAME_IN="$1"

# Make sure the image exists so that we can print an informative message if it doesn't
MATCHING_IMAGES=$(docker images -q $IMAGE_NAME_IN)
if [ -z $MATCHING_IMAGES ]; then
echo -e "$FAIL Error: $IMAGE_NAME_IN does not appear to be a locally-available docker image"
echo -e "Available docker image tags:"
echo -e "$(docker images | tail -n +2 | awk '{print $1}')"
echo -e " Hint: run \"docker image ls\" to print available docker images $ENDC"
exit
fi

if [ $# -ge 2 ]; then
# User-specified output path for .sif file
IMAGE_PATH_OUT="$2"
else
# Default to .sif file with same name as docker tag
IMAGE_PATH_OUT="$IMAGE_NAME_IN.sif"
fi

# Path to the output directory
OUT_DIR=$(dirname "$IMAGE_PATH_OUT")

# Make the output directory if it doesn't exist
if [ ! -d "$OUT_DIR" ]; then
mkdir -p "$OUT_DIR"
if [ -d "$OUT_DIR" ]; then
echo -e "$SUCCESS Created directory $DIR$OUT_DIR $ENDC"
else
echo -e "$FAIL Error: could not create directory $DIR$OUT_DIR $ENDC"
exit
fi
fi

# Absolute path to output directory
OUT_DIR_ABS=$(cd "$OUT_DIR"; pwd)

# Name of the output image
IMAGE_NAME_OUT=$(basename "$IMAGE_PATH_OUT")

# Absolute path to the output file
IMAGE_PATH_OUT_ABS="$OUT_DIR_ABS/$IMAGE_NAME_OUT"

# If the output file exists, ask if we want to overwrite it
if [ -f "$IMAGE_PATH_OUT_ABS" ]; then
while true; do
echo -e "$DIR$IMAGE_PATH_OUT_ABS$WARNING exists. Overwrite [y/N]? $ENDC"
read -p "" yn
case $yn in
[Yy]* ) break;;
[Nn]* ) exit;;
* ) exit;;
esac
done
fi

# Backup sif file if it already exists
if [ -f "$IMAGE_PATH_OUT_ABS" ]; then
IMAGE_PATH_ABS_BACKUP="$IMAGE_PATH_OUT_ABS.backup"
mv "$IMAGE_PATH_OUT_ABS" "$IMAGE_PATH_ABS_BACKUP"

if [ -f "$IMAGE_PATH_ABS_BACKUP" ]; then
echo -e "$SUCCESS Backed up $DIR$IMAGE_PATH_OUT_ABS $SUCCESS-->$DIR $IMAGE_PATH_ABS_BACKUP $ENDC"
fi
fi

# Inform the user that we're about to execute the export
echo -e "$SUCCESS Exporting docker image $DIR$IMAGE_NAME_IN $SUCCESS--> $DIR$IMAGE_PATH_OUT_ABS $ENDC"

# Export the docker image to a Singularity .sif file
docker run -v /var/run/docker.sock:/var/run/docker.sock -v "$OUT_DIR_ABS":/output -it --rm quay.io/singularity/docker2singularity --name $IMAGE_NAME_OUT $IMAGE_NAME_IN

# Check that the sif file actually got saved
if [ -f "$IMAGE_PATH_OUT_ABS" ]; then
echo -e "$SUCCESS Exported Docker image $IMAGE_NAME_IN --> $DIR$IMAGE_PATH_OUT_ABS $ENDC"

# Remove the backup image
if [ -f "$IMAGE_PATH_ABS_BACKUP" ]; then
rm "$IMAGE_PATH_ABS_BACKUP"
fi

else
# Replace the image with the backup image
if [ -f "$IMAGE_PATH_ABS_BACKUP" ]; then
echo -e "$WARNING Canceled exporting $DIR$IMAGE_NAME_IN $WARNING--> $DIR$IMAGE_PATH_OUT_ABS$ENDC"
mv "$IMAGE_PATH_ABS_BACKUP" "$IMAGE_PATH_OUT_ABS"
else
echo -e "$FAIL Warning: $DIR$IMAGE_PATH_OUT_ABS$FAIL not found; exporting docker image $IMAGE_NAME_IN --> $DIR$IMAGE_PATH_OUT_ABS$FAIL appears to have failed. $ENDC"
fi
fi

0 comments on commit 46bc853

Please sign in to comment.