Skip to content

Commit 7a0a088

Browse files
committed
Merge branch 'release/0.0.1'
2 parents 67299be + 2ef5465 commit 7a0a088

File tree

7 files changed

+259
-117
lines changed

7 files changed

+259
-117
lines changed

Dockerfile

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,30 @@ ENV DEBIAN_FRONTEND=noninteractive
66
RUN apt-get update
77
RUN apt-get install -y --no-install-recommends \
88
mysql-client \
9-
borgbackup \
109
wget
1110
RUN update-locale LANG=C.UTF-8
11+
12+
RUN wget -q https://github.com/borgbackup/borg/releases/download/1.0.10/borg-linux64
13+
RUN mv borg-linux64 /usr/local/sbin/borg
14+
RUN chown root:root /usr/local/sbin/borg
15+
RUN chmod 755 /usr/local/sbin/borg
16+
1217
RUN wget -qO- https://get.docker.com/ | sh
1318

1419
ADD scripts_common.sh /scripts_common.sh
1520
ADD setup.sh /etc/my_init.d/setup.sh
16-
ADD backup.sh /usr/local/sbin/backup
17-
ADD restore.sh /usr/local/sbin/restore
1821

19-
# Clean up for smaller image
22+
# add to $PATH:
23+
ADD backup.sh /usr/local/sbin/backup.sh
24+
ADD restore.sh /usr/local/sbin/restore.sh
25+
ADD list.sh /usr/local/sbin/list.sh
26+
27+
# add to / for simpler reference point for cron:
28+
RUN ln -s /usr/local/sbin/backup.sh /backup.sh
29+
30+
# clean up for smaller image
2031
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
2132

22-
# Baseimage init process
33+
# baseimage init process
2334
ENTRYPOINT ["/sbin/my_init"]
2435

README.md

Lines changed: 56 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
This image is mainly intended for backing up mysql dumps to local and/or remote [borg](https://github.com/borgbackup/borg) repos.
44
Other files may be included in the backup, and database dumps can be excluded altogether.
55

6-
The container features `backup` and `restore` scripts that can either be ran directly with docker,
7-
or by cron, latter being the preferred method.
6+
The container features `backup`, `restore` and `list` scripts that can either be ran
7+
directly with docker, or by cron, latter being the preferred method.
88

99
For cron and/or remote borg usage, you also need to mount container configuration
1010
at `/config`, containing ssh key (named `id_rsa`) and/or crontab file (named `crontab`).
@@ -18,6 +18,9 @@ the `backup` script (see below). Note that this requires mounting docker socket
1818
but keep in mind it has security implications (borg-mysql-backup will have essentially
1919
root permissions on the host).
2020

21+
Avoid using the `latest` version of this image, as you'd want to be tied to a certain
22+
version of borg - different borg versions can be non-compatible.
23+
2124

2225
## Container Parameters
2326

@@ -44,7 +47,7 @@ root permissions on the host).
4447

4548
## Script usage
4649

47-
Container incorporates `backup` and `restore` scripts.
50+
Container incorporates `backup`, `restore` and `list` scripts.
4851

4952
### backup
5053

@@ -86,14 +89,14 @@ directly via docker for one off backup.
8689
-e BORG_EXTRA_OPTS='--compression zlib,5 --lock-wait 60' \
8790
-e BORG_PASSPHRASE=borgrepopassword \
8891
-e BORG_PRUNE_OPTS='--keep-daily=7 --keep-weekly=4' \
89-
-v /backup:/backup:ro \
92+
-v /backup:/backup \
9093
-v /borg-mysql-backup/config:/config:ro \
9194
-v /app1-data-on-host:/app1-data:ro \
9295
layr/borg-mysql-backup
9396

9497
`/config/crontab` contents:
9598

96-
15 05 * * * root backup -d "App1 App2" -n /app1-data -p app1-app2
99+
15 05 * * * root /backup.sh -d "App1 App2" -n /app1-data -p app1-app2
97100

98101
##### Back up all databases daily at 04:10 and 16:10 to local&remote borg repos, stopping containers myapp1 & myapp2 for the process
99102

@@ -107,29 +110,29 @@ directly via docker for one off backup.
107110
-e BORG_PASSPHRASE=borgrepopassword \
108111
-e BORG_PRUNE_OPTS='--keep-daily=7 --keep-weekly=4' \
109112
-v /var/run/docker.sock:/var/run/docker.sock \
110-
-v /backup:/backup:ro \
113+
-v /backup:/backup \
111114
-v /borg-mysql-backup/config:/config:ro \
112115
layr/borg-mysql-backup
113116

114117
`/config/crontab` contents:
115118

116-
10 04,16 * * * root backup -d __all__ -p myapp-prefix -c "myapp1 myapp2"
119+
10 04,16 * * * root /backup.sh -d __all__ -p myapp-prefix -c "myapp1 myapp2"
117120

118121
##### Back up directores /app1 & /app2 every 6 hours to local borg repo (ie remote is excluded)
119122

120123
docker run -d \
121124
-e HOST_HOSTNAME=hostname-to-use-in-archive-prefix \
122125
-e BORG_PASSPHRASE=borgrepopassword \
123126
-e BORG_PRUNE_OPTS='--keep-daily=7 --keep-weekly=4' \
124-
-v /backup:/backup:ro \
127+
-v /backup:/backup \
125128
-v /borg-mysql-backup/config:/config:ro \
126129
-v /app1:/app1:ro \
127130
-v /app2:/app2:ro \
128131
layr/borg-mysql-backup
129132

130133
`/config/crontab` contents:
131134

132-
0 */6 * * * root backup -l -n "/app1 /app2" -p my_app_prefix
135+
0 */6 * * * root /backup.sh -l -n "/app1 /app2" -p my_app_prefix
133136

134137
Note we didn't need to define mysql- or remote borg repo related docker env vars.
135138
Also there's no need to have ssh key in `/config`, as we're not connecting to a remote server.
@@ -141,10 +144,10 @@ Also there's no need to have ssh key in `/config`, as we're not connecting to a
141144
-e REMOTE=remoteuser@server.com:repo/location \
142145
-e BORG_PASSPHRASE=borgrepopassword \
143146
-e BORG_PRUNE_OPTS='--keep-daily=7 --keep-weekly=4' \
144-
-v /backup:/backup:ro \
147+
-v /backup:/backup \
145148
-v /borg-mysql-backup/config:/config:ro \
146149
-v /app3/on/host:/app3:ro \
147-
layr/borg-mysql-backup -- backup -r -n /app3 -p my_prefix
150+
layr/borg-mysql-backup -- backup.sh -r -n /app3 -p my_prefix
148151

149152
Note there's no need to have a crontab file in `/config`, as container only lives until
150153
the `backup` command returns.
@@ -155,10 +158,7 @@ the `backup` command returns.
155158
Script will restore db from the restored dump, if respective param is provided. All data
156159
will be extracted into `/backup/restored-{archive_name}`
157160

158-
Repository contents can be listed with the `-L` option, or simply run directly `borg list`
159-
instead of `restore`
160-
161-
usage: restore [-h] [-d] [-c CONTAINERS] [-r] [-l] [-L]
161+
usage: restore [-h] [-d] [-c CONTAINERS] [-r] [-l]
162162
[-N BORG_LOCAL_REPO_NAME] -a ARCHIVE_NAME
163163

164164
Restore data from borg archive
@@ -172,32 +172,11 @@ instead of `restore`
172172
requires mounting the docker socket (-v /var/run/docker.sock:/var/run/docker.sock)
173173
-r restore from remote borg repo
174174
-l restore from local borg repo
175-
-L instead of restoring, simply list the repository contents and exit;
176-
in this case, naturally, -a option is not mandatory
177175
-N BORG_LOCAL_REPO_NAME overrides container env variable BORG_LOCAL_REPO_NAME; optional;
178176
-a ARCHIVE_NAME name of the borg archive to restore data from
179177

180178
#### Usage examples
181179

182-
##### List the local repository contents
183-
184-
docker run -it --rm \
185-
-e BORG_PASSPHRASE=borgrepopassword \
186-
-v /tmp:/backup:ro \
187-
layr/borg-mysql-backup -- restore -lL
188-
189-
##### List the remote repository contents
190-
191-
docker run -it --rm \
192-
-e BORG_EXTRA_OPTS="-P my-prefix" \
193-
-e REMOTE=remoteuser@server.com:repo/location \
194-
-e BORG_PASSPHRASE=borgrepopassword \
195-
-v /borg-mysql-backup/config:/config:ro \
196-
layr/borg-mysql-backup -- restore -rL
197-
198-
Note the `BORG_EXTRA_OPTS`, `BORG_LOCAL_EXTRA_OPTS`, `BORG_REMOTE_EXTRA_OPTS` env
199-
variables are still usable with -L option.
200-
201180
##### Restore archive from remote borg repo & restore mysql with restored dumpfile
202181

203182
docker run -it --rm \
@@ -207,16 +186,16 @@ variables are still usable with -L option.
207186
-e MYSQL_PASS=password \
208187
-e REMOTE=remoteuser@server.com:repo/location \
209188
-e BORG_PASSPHRASE=borgrepopassword \
210-
-v /tmp:/backup:ro \
189+
-v /tmp:/backup \
211190
-v /borg-mysql-backup/config:/config:ro \
212-
layr/borg-mysql-backup -- restore -r -d -a my_prefix-HOSTNAME-2017-02-27-160159
191+
layr/borg-mysql-backup -- restore.sh -r -d -a my_prefix-HOSTNAME-2017-02-27-160159
213192

214193
##### Restore archive from local borg repo & stop container app1 beforehand
215194

216195
docker run -it --rm \
217196
-e BORG_PASSPHRASE=borgrepopassword \
218-
-v /tmp:/backup:ro \
219-
layr/borg-mysql-backup -- restore -l -c app1 -a my_prefix-HOSTNAME-2017-02-27-160159
197+
-v /tmp:/backup \
198+
layr/borg-mysql-backup -- restore.sh -l -c app1 -a my_prefix-HOSTNAME-2017-02-27-160159
220199

221200
Note there's no need to mount `/config`, as we're not using cron nor connecting to remote borg.
222201
Also we're not providing mysql env vars, as script isn't invoked with `-d` option, meaning
@@ -225,9 +204,44 @@ db won't be automatically restored with the included .sql dumpfile (if there was
225204
##### Restore archive from non-default local borg repo
226205

227206
docker run -it --rm \
228-
-v /tmp:/backup:ro \
229-
layr/borg-mysql-backup -- restore -l -N otherrepo -a my_prefix-HOSTNAME-2017-02-27-160159
207+
-v /tmp:/backup \
208+
layr/borg-mysql-backup -- restore.sh -l -N otherrepo -a my_prefix-HOSTNAME-2017-02-27-160159
230209

231210
Data will be restored from non-default local borg repo `otherrepo`. Also note missing `BORG_PASSPHRASE`,
232211
which is required to be typed in manually.
233212

213+
### list
214+
215+
`list` script is for listing archives in a borg repo.
216+
217+
usage: list [-h] [-r] [-l] [-N BORG_LOCAL_REPO_NAME]
218+
219+
List archives in a borg repository
220+
221+
arguments:
222+
-h show help and exit
223+
-r list remote borg repo
224+
-l list local borg repo
225+
-N BORG_LOCAL_REPO_NAME overrides container env variable BORG_LOCAL_REPO_NAME; optional;
226+
227+
#### Usage examples
228+
229+
##### List the local repository contents
230+
231+
docker run -it --rm \
232+
-e BORG_PASSPHRASE=borgrepopassword \
233+
-v /tmp:/backup \
234+
layr/borg-mysql-backup -- list.sh -l
235+
236+
##### List the remote repository contents
237+
238+
docker run -it --rm \
239+
-e BORG_EXTRA_OPTS="-P my-prefix" \
240+
-e REMOTE=remoteuser@server.com:repo/location \
241+
-e BORG_PASSPHRASE=borgrepopassword \
242+
-v /borg-mysql-backup/config:/config:ro \
243+
layr/borg-mysql-backup -- list.sh -r
244+
245+
Note the `BORG_EXTRA_OPTS`, `BORG_LOCAL_EXTRA_OPTS`, `BORG_REMOTE_EXTRA_OPTS` env
246+
variables are still usable with `list`.
247+

backup.sh

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
#
33
# backs up mysql dump and/or other data to local and/or remote borg repository
44

5+
readonly SELF="${0##*/}"
6+
readonly LOG="/var/log/${SELF}.log"
57

68
readonly usage="
7-
usage: ${0##*/} [-h] [-d MYSQL_DBS] [-n NODES_TO_BACKUP] [-c CONTAINERS]
9+
usage: $SELF [-h] [-d MYSQL_DBS] [-n NODES_TO_BACKUP] [-c CONTAINERS]
810
[-r] [-l] [-P BORG_PRUNE_OPTS] [-N BORG_LOCAL_REPO_NAME] -p PREFIX
911
1012
Create new archive
@@ -63,13 +65,44 @@ dump_db() {
6365
}
6466

6567

68+
backup_local() {
69+
borg create -v --stats \
70+
$BORG_EXTRA_OPTS \
71+
$BORG_LOCAL_EXTRA_OPTS \
72+
"$BORG_LOCAL_REPO"::"$ARCHIVE_NAME" \
73+
"${NODES_TO_BACK_UP[@]}" || err "local borg create failed with [$?]"
74+
75+
borg prune -v --list \
76+
"$BORG_LOCAL_REPO" \
77+
--prefix "$PREFIX_WITH_HOSTNAME" \
78+
$BORG_PRUNE_OPTS || err "local borg prune failed with [$?]"
79+
}
80+
81+
82+
backup_remote() {
83+
# duplicate to remote location: (http://borgbackup.readthedocs.io/en/latest/faq.html#can-i-copy-or-synchronize-my-repo-to-another-location)
84+
borg create -v --stats \
85+
$BORG_EXTRA_OPTS \
86+
$BORG_REMOTE_EXTRA_OPTS \
87+
"$REMOTE"::"$ARCHIVE_NAME" \
88+
"${NODES_TO_BACK_UP[@]}" || err "remote borg create failed with [$?]"
89+
90+
borg prune -v --list \
91+
"$REMOTE" \
92+
--prefix "$PREFIX_WITH_HOSTNAME" \
93+
$BORG_PRUNE_OPTS || err "remote borg prune failed with [$?]"
94+
}
95+
96+
6697
# backup selected data
98+
# note the borg processes are executed in a sub-shell, so local & remote backup could be
99+
# run in parallel
67100
do_backup() {
68-
local start_time end_time
101+
local started_pids
69102

70-
readonly start_time="$(date +%H:%M:%S)"
103+
declare -a started_pids=()
71104

72-
echo "=> Backup started at [$start_time]"
105+
log "=> Backup started"
73106

74107
dump_db || fail "db dump failed with [$?]"
75108
expand_nodes_to_back_up
@@ -78,35 +111,19 @@ do_backup() {
78111
pushd -- "$TMP" || fail "unable to pushd into [$TMP]" # cd there because files in $TMP are added without full path (to avoid "$TMP_ROOT" prefix in borg repo)
79112

80113
if [[ "$REMOTE_ONLY" -ne 1 ]]; then
81-
borg create -v --stats \
82-
$BORG_EXTRA_OPTS \
83-
$BORG_LOCAL_EXTRA_OPTS \
84-
"$BORG_LOCAL_REPO"::"$ARCHIVE_NAME" \
85-
"${NODES_TO_BACK_UP[@]}"
86-
87-
borg prune -v --list \
88-
"$BORG_LOCAL_REPO" \
89-
--prefix "$PREFIX_WITH_HOSTNAME" \
90-
$BORG_PRUNE_OPTS
114+
backup_local &
115+
started_pids+=("$!")
91116
fi
92117

93118
if [[ "$LOCAL_ONLY" -ne 1 ]]; then
94-
# duplicate to remote location: (http://borgbackup.readthedocs.io/en/latest/faq.html#can-i-copy-or-synchronize-my-repo-to-another-location)
95-
borg create -v --stats \
96-
$BORG_EXTRA_OPTS \
97-
$BORG_REMOTE_EXTRA_OPTS \
98-
"$REMOTE"::"$ARCHIVE_NAME" \
99-
"${NODES_TO_BACK_UP[@]}"
100-
101-
borg prune -v --list \
102-
"$REMOTE" \
103-
--prefix "$PREFIX_WITH_HOSTNAME" \
104-
$BORG_PRUNE_OPTS
119+
backup_remote &
120+
started_pids+=("$!")
105121
fi
106122

107-
popd
108-
readonly end_time="$(date +%H:%M:%S)"
109-
echo "=> Backup finished at [$end_time]"
123+
wait "${started_pids[@]}"
124+
125+
popd &> /dev/null
126+
log "=> Backup finished"
110127

111128
return 0
112129
}
@@ -160,7 +177,7 @@ validate_config() {
160177
fi
161178

162179
[[ "$REMOTE_OR_LOCAL_OPT_COUNTER" -gt 1 ]] && fail "-r & -l options are exclusive"
163-
[[ -d "$BACKUP_ROOT" ]] || fail "[$BACKUP_ROOT] is not mounted"
180+
[[ "$REMOTE_ONLY" -ne 1 && ! -d "$BACKUP_ROOT" ]] && fail "[$BACKUP_ROOT] is not mounted"
164181
[[ "$BORG_LOCAL_REPO_NAME" == /* ]] && fail "BORG_LOCAL_REPO_NAME should not start with a slash"
165182

166183
if [[ "$LOCAL_ONLY" -ne 1 && "$-" != *i* ]]; then
@@ -184,7 +201,7 @@ cleanup() {
184201
# Entry
185202
# ================
186203
trap -- 'cleanup; exit' EXIT HUP INT QUIT PIPE TERM
187-
source /scripts_common.sh || { echo -e "failed to import /scripts_common.sh"; exit 1; }
204+
source /scripts_common.sh || { echo -e " ERROR: failed to import /scripts_common.sh" | tee "$LOG"; exit 1; }
188205
source /env_vars.sh || fail "failed to import /env_vars.sh"
189206
REMOTE_OR_LOCAL_OPT_COUNTER=0
190207

0 commit comments

Comments
 (0)