forked from balena-os/balenaos-in-container
-
Notifications
You must be signed in to change notification settings - Fork 0
/
balenaos-in-container.sh
executable file
·189 lines (176 loc) · 4.71 KB
/
balenaos-in-container.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
#!/bin/bash
set -e
config_path=""
docker_prefix="balena-"
docker_postfix="$RANDOM"
clean_volumes=no
docker_extra_args=""
detach=""
no_tty="-ti"
function help {
cat << EOF
Run balenaOS image in a docker container.
$0 <ARGUMENTS>
ARGUMENTS:
-h, --help
Print this message.
--image <image>
Docker image to be used as balenaOS.
Mandatory argument.
--prefix <prefix>
Use a specific prefix for the docker container and volumes. This allows for
reusing volumes.
Default: "balena-"
--id <id>
Use a specific id for the docker container and volumes. This allows for
reusing volumes.
Default: randomly generated.
-c, --config <config>
The config.json path. This you can download from balena.io dashboard.
Mandatory argument.
-d, --detach
Run the container in the background and print container ID (just like "docker run -d")
Default: no.
--extra-args <arguments>
Additional arguments for docker run (e.g. to add bind mounts)
--clean-volumes
If volumes are not planned to be reused, you can take advantage of this
argument to clean up the system. Cannot be used together with -d.
Default: no.
--no-tty
Don't allocate a pseudo-TTY and don't keep STDIN open (docker run without "-it").
Default: no.
EOF
}
# realpath is not available on Mac OS, define it as a bash function if it's not found
command -v realpath >/dev/null 2>&1 || {
realpath() {
[[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}
}
# Parse arguments
while [[ $# -ge 1 ]]; do
i="$1"
case $i in
-h|--help)
help
exit 0
;;
--image)
if [ -z "$2" ]; then
log ERROR "\"$1\" argument needs a value."
fi
image="$2"
shift
;;
--prefix)
if [ -z "$2" ]; then
log ERROR "\"$1\" argument needs a value."
fi
docker_prefix="$2"
shift
;;
--id)
if [ -z "$2" ]; then
log ERROR "\"$1\" argument needs a value."
fi
docker_postfix="$2"
shift
;;
-c|--config)
config_json="$(realpath "$2")"
if [ ! -f "$config_json" ]; then
echo "ERROR: $config_path no such file."
exit 1
fi
shift
;;
-d|--detach)
detach="--detach"
;;
--extra-args)
docker_extra_args="$2"
shift
;;
--clean-volumes)
clean_volumes=yes
;;
--no-tty)
no_tty=""
;;
*)
echo "ERROR: Unrecognized option $1."
help
exit 1
;;
esac
shift
done
if [ -z "$image" ] || [ -z "$config_json" ]; then
echo "ERROR: Required arguments not provided."
help
exit 1
fi
if ! docker info &> /dev/null; then
echo "ERROR: Docker needs to be running on your host machine."
exit 1
fi
# Get absolute path of the script location
# In this way we can reference any file relative to the script path easily
# Get the absolute script location
SCRIPTPATH="$(cd "$(dirname "$0")" ; pwd)"
for volume in boot state data; do
if docker volume inspect "${docker_prefix}${volume}-${docker_postfix}" &> /dev/null; then
echo "INFO: Reusing ${docker_prefix}${volume}-${docker_postfix} docker volume..."
else
echo "INFO: Creating ${docker_prefix}${volume}-${docker_postfix} docker volume..."
docker volume create "${docker_prefix}${volume}-${docker_postfix}" &> /dev/null
fi
done
balena_boot_volume="${docker_prefix}boot-${docker_postfix}:/mnt/boot"
balena_state_volume="${docker_prefix}state-${docker_postfix}:/mnt/state"
balena_data_volume="${docker_prefix}data-${docker_postfix}:/mnt/data"
# Populate the boot volume with the config.json
docker run -i --rm -v \
"$balena_boot_volume" -v "$config_json":/config.json \
"$image" sh << EOF
if ! [ -f /mnt/boot/config.json ]; then
cp /config.json /mnt/boot/config.json
else
echo "INFO: Reusing already existing config.json in docker volume."
fi
EOF
container_name="${docker_prefix}container-${docker_postfix}"
echo "INFO: Running balenaOS as container ${container_name} ..."
#shellcheck disable=SC2086
if docker run $no_tty --rm --privileged \
-e "container=docker" \
--stop-timeout=30 \
--dns 127.0.0.2 \
--name "${container_name}" \
--stop-signal SIGRTMIN+3 \
-v /lib/modules:/lib/modules:ro \
-v "$SCRIPTPATH/conf/systemd-watchdog.conf:/etc/systemd/system.conf.d/watchdog.conf:ro" \
-v "$balena_boot_volume" \
-v "$balena_state_volume" \
-v "$balena_data_volume" \
$docker_extra_args \
$detach \
"$image" \
/sbin/init; then
if [ "$detach" != "" ]; then
echo "INFO: balenaOS container running as ${container_name}"
else
echo "ERROR: Running docker container."
fi
else
if [ "$detach" != "" ]; then
echo "ERROR: Running docker container."
else
echo "INFO: balenaOS container stopped."
fi
fi
if [ "$detach" = "" ] && [ "$clean_volumes" = "yes" ]; then
echo "Cleaning volumes..."
docker volume rm "${docker_prefix}boot-${docker_postfix}" "${docker_prefix}state-${docker_postfix}" "${docker_prefix}data-${docker_postfix}" &> /dev/null
fi