-
Notifications
You must be signed in to change notification settings - Fork 3
/
docker2singularity.sh
150 lines (115 loc) · 5.75 KB
/
docker2singularity.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#! /bin/bash
#
# docker2singularity.sh will convert a docker image into a singularity
# Must be run with sudo to use docker commands (eg aufs)
#
# NOTES:
# If the docker image uses both ENTRYPOINT and CMD the latter will be ignored
#
# KNOWN ISSUES:
# Currently ENTRYPOINTs and CMDs with commas in the arguments are not supported
#
# USAGE: docker2singularity.sh ubuntu:14.04
set -o errexit
set -o nounset
usage="$0 ubuntu:14.04"
if [ -z $1 ]; then
echo $usage;
exit 0;
else
image=$1
fi
################################################################################
### CONTAINER RUNNING ID #######################################################
################################################################################
runningid=`docker run -d $image tail -f /dev/null`
# Full id looks like
# sha256:d59bdb51bb5c4fb7b2c8d90ae445e0720c169c553bcf553f67cb9dd208a4ec15
# Take the first 12 characters to get id of container
container_id=`echo ${runningid} | cut -c1-12`
# Network address, if needed
network_address=`docker inspect --format="{{.NetworkSettings.IPAddress}}" $container_id`
################################################################################
### IMAGE NAME #################################################################
################################################################################
image_name=`docker inspect --format="{{.Config.Image}}" $container_id`
# using bash substitution
# removing special chars [perhaps echo + sed would be better for other chars]
image_name=${image_name/\//_}
# following is the date of the container, not the docker image.
#creation_date=`docker inspect --format="{{.Created}}" $container_id`
creation_date=`docker inspect --format="{{.Created}}" $image`
################################################################################
### IMAGE SIZE #################################################################
################################################################################
size=`docker inspect --format="{{.Size}}" $image`
# convert size in MB (it seems too small for singularity containers ...?). Add 1MB to round up (minimum).
size=`echo $(($size/1000000+1))`
# adding half of the container size seems to work (do not know why exactly...?)
# I think it would be Ok by adding 1/3 of the size.
size=`echo $(($size+$size/2))`
echo "Size: $size MB for the singularity container"
################################################################################
### IMAGE CREATION #############################################################
################################################################################
TMPDIR=$(mktemp -u -d)
mkdir -p $TMPDIR
creation_date=`echo ${creation_date} | cut -c1-10`
new_container_name=$image_name-$creation_date-$container_id.img
singularity create -s $size $new_container_name
docker export $container_id | singularity import $new_container_name
docker inspect $container_id >> $TMPDIR/singularity.json
singularity copy $new_container_name $TMPDIR/singularity.json /
# Bootstrap the image to set up scripts for environment setup
singularity bootstrap $new_container_name
chmod a+rw -R $TMPDIR
################################################################################
### SINGULARITY RUN SCRIPT #####################################################
################################################################################
CMD=$(docker inspect --format='{{json .Config.Cmd}}' $image)
if [[ $CMD != [* ]]; then
if [[ $CMD != "null" ]]; then
CMD="/bin/sh -c "$CMD
fi
fi
# Remove quotes, commas, and braces
CMD=`echo "${CMD//\"/}" | sed 's/\[//g' | sed 's/\]//g' | sed 's/,//g'`
ENTRYPOINT=$(docker inspect --format='{{json .Config.Entrypoint}}' $image)
if [[ $ENTRYPOINT != [* ]]; then
if [[ $ENTRYPOINT != "null" ]]; then
ENTRYPOINT="/bin/sh -c "$ENTRYPOINT
fi
fi
# Remove quotes, commas, and braces
ENTRYPOINT=`echo "${ENTRYPOINT//\"/}" | sed 's/\[//g' | sed 's/\]//g' | sed 's/,//g'`
echo '#!/bin/sh' > $TMPDIR/singularity
if [[ $ENTRYPOINT != "null" ]]; then
echo $ENTRYPOINT '$@' >> $TMPDIR/singularity;
else
if [[ $CMD != "null" ]]; then
echo $CMD '$@' >> $TMPDIR/singularity;
fi
fi
chmod +x $TMPDIR/singularity
singularity copy $new_container_name $TMPDIR/singularity /
################################################################################
### SINGULARITY ENVIRONMENT ####################################################
################################################################################
docker run --rm --entrypoint="/usr/bin/env" $image > $TMPDIR/docker_environment
# don't include HOME and HOSTNAME - they mess with local config
sed -i '/^HOME/d' $TMPDIR/docker_environment
sed -i '/^HOSTNAME/d' $TMPDIR/docker_environment
sed -i 's/^/export /' $TMPDIR/docker_environment
singularity copy $new_container_name $TMPDIR/docker_environment /
singularity exec --writable $new_container_name /bin/sh -c "echo '. /docker_environment' >> /environment"
rm -rf $TMPDIR
################################################################################
### Permissions ################################################################
################################################################################
# making sure that any user can read and execute everything in the container
echo "Fixing permissions."
singularity exec --writable --contain $new_container_name /bin/sh -c "find /* -maxdepth 0 -not -path '/dev*' -not -path '/proc*' -not -path '/sys*' -exec chmod a+r -R '{}' \;"
singularity exec --writable --contain $new_container_name /bin/sh -c "find / -executable -perm -u+x,o-x -not -path '/dev*' -not -path '/proc*' -not -path '/sys*' -exec chmod a+x '{}' \;"
echo "Stopping container, please wait."
docker stop $container_id
mv $new_container_name /output/$new_container_name