-
Notifications
You must be signed in to change notification settings - Fork 1
/
project.sh
executable file
·243 lines (201 loc) · 6.37 KB
/
project.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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
#!/usr/bin/env bash
# Fancy prints
print_normal (){ printf "%b\n" "$1" >&2; }
print_error (){ printf "$(tput setaf 1)[project.sh] %b$(tput sgr0)\n" "$1" >&2; }
print_info (){ printf "$(tput setaf 3)[project.sh] %b$(tput sgr0)\n" "$1" >&2; }
print_success(){ printf "$(tput setaf 2)[project.sh] %b$(tput sgr0)\n" "$1" >&2; }
# Abort in the case of an error
handle_error(){
if [ $1 -ne 0 ]; then
print_error "Something went wrong while $2, aborting."
exit 1
fi
}
## CUSTOMIZE
RUBY_VERSION=2.1
APP_NAME=upliftinglemma-net
PORT=3000
custom_bootstrap(){
# Custom bootstrap instructions go here.
# This is the last bootstrap step; it is run after the first `bundle install`.
# Since this application has a db, you'll probably want to `rake db:setup`.
print_info "Setting up the database (rake db:setup)"
docker-compose run web bundle exec rake db:setup
handle_error $? "stopping the database"
}
## /CUSTOMIZE
DOCKER_MINIMAL_IMAGE=tianon/true
GEMS_CONTAINER_NAME=gems-$RUBY_VERSION
DB_DATA_CONTAINER_NAME=$APP_NAME-db-data
PROJECT_PREFIX=$(echo ${PWD##*/} | tr -d '-')
# `docker info` call for testing if the Docker host is reachable.
# Usage: check_docker
check_docker(){
docker info > /dev/null 2>&1
if [ $? -ne 0 ]; then
print_error "ERROR: Docker host could not be reached. Maybe you need sudo?"
exit 1
fi
}
# Create a data volume container for a specific path.
# Usage: create_data_container CONTAINER_NAME VOLUME_PATH
create_data_container(){
docker run -d --name $1 -v $2 $DOCKER_MINIMAL_IMAGE
}
# Stop a container by name.
# Usage: stop_container_by_name CONTAINER_NAME
stop_container_by_name(){
docker ps -a | grep $1 | awk '{ print $1 }' | xargs --no-run-if-empty docker stop
}
# Remove a container by name.
# Usage: remove_container_by_name CONTAINER_NAME
remove_container_by_name(){
docker ps -a | grep $1 | awk '{ print $1 }' | xargs --no-run-if-empty docker rm
}
# Remove an image by name.
# Usage: remove_image_by_name IMAGE_NAME
remove_image_by_name(){
docker images -a | grep $1 | awk '{ print $3 }' | xargs --no-run-if-empty docker rmi
}
# Main options
bootstrap(){
# Announcing
print_info "Bootstrapping $APP_NAME"
print_info "Ruby version: $RUBY_VERSION"
# Check if the Gems container already exists. If not, create it.
local GEMS_CONTAINER=$(docker ps -a | grep $GEMS_CONTAINER_NAME)
if [ -n "$GEMS_CONTAINER" ]; then
print_success "The gems container for Ruby $RUBY_VERSION ($GEMS_CONTAINER_NAME) already exists."
else
print_info "Creating the gems container for Ruby $RUBY_VERSION ($GEMS_CONTAINER_NAME)."
create_data_container $GEMS_CONTAINER_NAME "/usr/local/bundle"
handle_error $? "creating $GEMS_CONTAINER_NAME"
print_success "Gems container for Ruby $RUBY_VERSION ($GEMS_CONTAINER_NAME) successfully created."
fi
# Check if the database data container already exists. If not, create it.
if [ -n "$(docker ps -a | grep $DB_DATA_CONTAINER_NAME)" ]; then
print_success "The database data container ($DB_DATA_CONTAINER_NAME) already exists."
else
print_info "Creating the database data container ($DB_DATA_CONTAINER_NAME)."
create_data_container $DB_DATA_CONTAINER_NAME "/var/lib/postgresql/data/"
handle_error $? "creating $DB_DATA_CONTAINER_NAME"
print_success "Database data container ($DB_DATA_CONTAINER_NAME) successfully created."
fi
# Build the web container
print_info "Building the web container."
docker-compose build web
handle_error $? "building the web container"
# Check if the gems container was just created; if so, install bundler.
if [ -z "$GEMS_CONTAINER" ]; then
print_info "Gems container is new, installing bundler."
docker-compose run web gem install bundler
handle_error $? "installing bundler"
else
print_info "Gems container already existed before this script: assuming bundler is already installed."
print_info "In the case of failure, run"
print_info " docker-compose run web gem install bundler"
print_info "and re-run this script."
fi
# Install app's dependencies
print_normal
print_info "Installing dependencies (bundle install)"
docker-compose run web bundle install --jobs 4 --retry 3
handle_error $? "installing the app's dependencies"
custom_bootstrap
print_normal
print_success "The project was successfully setup! Run"
print_success " $0 start"
print_success "to start the server."
}
start(){
# If requested, start the nginx server.
local SERVICES="db web"
[ "$1" = "--nginx" ] && SERVICES="nginx $SERVICES"
# Assume Docker host is localhost, override in the case boot2docker is detected
local URL=http://localhost/
command -v boot2docker > /dev/null 2>&1 && URL=http://$(boot2docker ip 2> /dev/null)/
[ "$PORT" != "80" ] && URL="$URL:$PORT"
print_info "Open $URL on your browser."
print_normal
docker-compose up $SERVICES
}
bundle_exec(){
# Teaching docker-compose commands, one at a time.
local command=$(echo ${@})
print_info "Running"
print_info " docker-compose run web bundle exec $command"
docker-compose run web bundle exec $command
}
bundle_install(){
# Teaching docker-compose commands, one at a time.
print_info "Running"
print_info " docker-compose run web bundle install"
docker-compose run web bundle install
}
stop(){
docker-compose stop
}
clean(){
stop_container_by_name $PROJECT_PREFIX
remove_container_by_name $PROJECT_PREFIX
remove_image_by_name $PROJECT_PREFIX
}
project_clean(){
clean
remove_container_by_name $DB_DATA_CONTAINER_NAME
}
gems_clean(){
remove_container_by_name $GEMS_CONTAINER_NAME
}
untagged_clean(){
remove_image_by_name '^<none>' 2> /dev/null
}
check_docker
case "$1" in
"bootstrap")
bootstrap
;;
"start")
start ${@:2}
;;
"exec")
bundle_exec ${@:2}
;;
"install")
bundle_install
;;
"console")
bundle_exec "rails console" ${@:2}
;;
"stop")
stop
;;
"clean")
clean
;;
"project-clean")
project_clean
;;
"gems-clean")
gems_clean
;;
"untagged-clean")
untagged_clean
;;
*)
print_normal "Usage: $0 COMMAND"
print_normal
print_normal "Available commands:"
print_normal " bootstrap"
print_normal " start"
print_normal " stop"
print_normal " exec"
print_normal " install"
print_normal " console"
print_normal " clean"
print_normal " project-clean"
print_normal " gems-clean"
print_normal " untagged-clean"
;;
esac
exit 0