feat: add minecraft backup integration
This commit is contained in:
parent
b0650c0425
commit
db0e7799e0
|
@ -1,11 +1,82 @@
|
|||
FROM restic/restic:0.9.6
|
||||
FROM alpine AS builder
|
||||
|
||||
RUN apk update && apk add python3 dcron mariadb-client postgresql-client
|
||||
RUN mkdir -p /opt
|
||||
|
||||
ARG IMAGE_ARCH=amd64
|
||||
|
||||
ARG RCON_CLI_VERSION=1.4.4
|
||||
|
||||
ADD https://github.com/itzg/rcon-cli/releases/download/${RCON_CLI_VERSION}/rcon-cli_${RCON_CLI_VERSION}_linux_${IMAGE_ARCH}.tar.gz /tmp/rcon-cli.tar.gz
|
||||
|
||||
RUN tar x -f /tmp/rcon-cli.tar.gz -C /opt/ && \
|
||||
chmod +x /opt/rcon-cli
|
||||
|
||||
ARG RESTIC_VERSION=0.9.5
|
||||
|
||||
ADD https://github.com/restic/restic/releases/download/v${RESTIC_VERSION}/restic_${RESTIC_VERSION}_linux_${IMAGE_ARCH}.bz2 /tmp/restic.bz2
|
||||
|
||||
RUN bunzip2 /tmp/restic.bz2 && \
|
||||
mv /tmp/restic /opt/restic && \
|
||||
chmod +x /opt/restic
|
||||
|
||||
ARG DEMOTER_VERSION=0.1.0
|
||||
|
||||
ADD https://github.com/itzg/entrypoint-demoter/releases/download/${DEMOTER_VERSION}/entrypoint-demoter_${DEMOTER_VERSION}_linux_${IMAGE_ARCH}.tar.gz /tmp/entrypoint-demoter.tar.gz
|
||||
|
||||
RUN tar x -f /tmp/entrypoint-demoter.tar.gz -C /opt/ && \
|
||||
chmod +x /opt/entrypoint-demoter
|
||||
|
||||
ARG RCLONE_VERSION=1.49.5
|
||||
|
||||
ADD https://downloads.rclone.org/v${RCLONE_VERSION}/rclone-v${RCLONE_VERSION}-linux-${IMAGE_ARCH}.zip /tmp/rclone.zip
|
||||
|
||||
RUN mkdir -p /tmp/rclone && \
|
||||
unzip /tmp/rclone.zip -d /tmp/rclone && \
|
||||
mv /tmp/rclone/rclone-v${RCLONE_VERSION}-linux-${IMAGE_ARCH}/rclone /opt/rclone && \
|
||||
chmod +x /opt/rclone
|
||||
|
||||
|
||||
FROM alpine
|
||||
|
||||
RUN apk -U --no-cache add \
|
||||
bash \
|
||||
coreutils \
|
||||
openssh-client \
|
||||
python3 \
|
||||
dcron \
|
||||
mariadb-client \
|
||||
postgresql-client
|
||||
|
||||
COPY --from=builder /opt/rcon-cli /opt/rcon-cli
|
||||
|
||||
RUN ln -s /opt/rcon-cli /usr/bin
|
||||
|
||||
COPY --from=builder /opt/restic /opt/restic
|
||||
|
||||
RUN ln -s /opt/restic /usr/bin
|
||||
|
||||
|
||||
COPY --from=builder /opt/entrypoint-demoter /opt/entrypoint-demoter
|
||||
|
||||
RUN ln -s /opt/entrypoint-demoter /usr/bin
|
||||
|
||||
|
||||
COPY --from=builder /opt/rclone /opt/rclone
|
||||
|
||||
RUN ln -s /opt/rclone /usr/bin
|
||||
|
||||
# install rcb python app
|
||||
|
||||
ADD . /restic-compose-backup
|
||||
WORKDIR /restic-compose-backup
|
||||
|
||||
RUN pip3 install -U pip setuptools wheel && pip3 install -e .
|
||||
ENV XDG_CACHE_HOME=/cache
|
||||
|
||||
# end install
|
||||
|
||||
ADD backup.sh /backup.sh
|
||||
RUN chmod +x ./backup.sh
|
||||
|
||||
ENTRYPOINT []
|
||||
CMD ["./entrypoint.sh"]
|
||||
CMD ["./entrypoint.sh"]
|
|
@ -0,0 +1,162 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [ "${DEBUG:-false}" == "true" ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
: "${RCON_HOST:=localhost}"
|
||||
: "${RCON_PORT:=25575}"
|
||||
: "${RCON_PASSWORD:=minecraft}"
|
||||
|
||||
export RCON_HOST
|
||||
export RCON_PORT
|
||||
export RCON_PASSWORD
|
||||
|
||||
###############
|
||||
## common ##
|
||||
## functions ##
|
||||
###############
|
||||
|
||||
is_elem_in_array() {
|
||||
# $1 = element
|
||||
# All remaining arguments are array to search for the element in
|
||||
if [ "$#" -lt 2 ]; then
|
||||
log INTERNALERROR "Wrong number of arguments passed to is_elem_in_array function"
|
||||
return 2
|
||||
fi
|
||||
local element="${1}"
|
||||
shift
|
||||
local e
|
||||
for e; do
|
||||
if [ "${element}" == "${e}" ]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
log() {
|
||||
if [ "$#" -lt 1 ]; then
|
||||
log INTERNALERROR "Wrong number of arguments passed to log function"
|
||||
return 2
|
||||
fi
|
||||
local level="${1}"
|
||||
shift
|
||||
local valid_levels=(
|
||||
"INFO"
|
||||
"WARN"
|
||||
"ERROR"
|
||||
"INTERNALERROR"
|
||||
)
|
||||
if ! is_elem_in_array "${level}" "${valid_levels[@]}"; then
|
||||
log INTERNALERROR "Log level ${level} is not a valid level."
|
||||
return 2
|
||||
fi
|
||||
(
|
||||
# If any arguments are passed besides log level
|
||||
if [ "$#" -ge 1 ]; then
|
||||
# then use them as log message(s)
|
||||
<<<"${*}" cat -
|
||||
else
|
||||
# otherwise read log messages from standard input
|
||||
cat -
|
||||
fi
|
||||
if [ "${level}" == "INTERNALERROR" ]; then
|
||||
echo "Please report this: https://github.com/itzg/docker-mc-backup/issues"
|
||||
fi
|
||||
) | awk -v level="${level}" '{ printf("%s %s %s\n", strftime("%FT%T%z"), level, $0); fflush(); }'
|
||||
} >&2
|
||||
|
||||
retry() {
|
||||
if [ "$#" -lt 3 ]; then
|
||||
log INTERNALERROR "Wrong number of arguments passed to retry function"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# How many times should we retry?
|
||||
# Value smaller than zero means infinitely
|
||||
local retries="${1}"
|
||||
# Time to sleep between retries
|
||||
local interval="${2}"
|
||||
readonly retries interval
|
||||
shift 2
|
||||
|
||||
if (( retries < 0 )); then
|
||||
local retries_msg="infinite"
|
||||
else
|
||||
local retries_msg="${retries}"
|
||||
fi
|
||||
|
||||
local i=-1 # -1 since we will increment it before printing
|
||||
while (( retries >= ++i )) || [ "${retries_msg}" != "${retries}" ]; do
|
||||
# Send SIGINT after 5 minutes. If it doesn't shut down in 30 seconds, kill it.
|
||||
if output="$(timeout --signal=SIGINT --kill-after=30s 5m "${@}" 2>&1 | tr '\n' '\t')"; then
|
||||
log INFO "Command executed successfully ${*}"
|
||||
return 0
|
||||
else
|
||||
log ERROR "Unable to execute ${*} - try ${i}/${retries_msg}. Retrying in ${interval}"
|
||||
if [ -n "${output}" ]; then
|
||||
log ERROR "Failure reason: ${output}"
|
||||
fi
|
||||
fi
|
||||
# shellcheck disable=SC2086
|
||||
sleep ${interval}
|
||||
done
|
||||
return 2
|
||||
}
|
||||
|
||||
is_function() {
|
||||
if [ "${#}" -ne 1 ]; then
|
||||
log INTERNALERROR "is_function expects 1 argument, received ${#}"
|
||||
fi
|
||||
name="${1}"
|
||||
[ "$(type -t "${name}")" == "function" ]
|
||||
}
|
||||
|
||||
call_if_function_exists() {
|
||||
if [ "${#}" -lt 1 ]; then
|
||||
log INTERNALERROR "call_if_function_exists expects at least 1 argument, received ${#}"
|
||||
return 2
|
||||
fi
|
||||
function_name="${1}"
|
||||
if is_function "${function_name}"; then
|
||||
eval "${@}"
|
||||
else
|
||||
log INTERNALERROR "${function_name} is not a valid function!"
|
||||
return 2
|
||||
fi
|
||||
}
|
||||
|
||||
##########
|
||||
## main ##
|
||||
##########
|
||||
|
||||
|
||||
log INFO "waiting for rcon readiness..."
|
||||
# 20 times, 10 second delay
|
||||
retry 20 10s rcon-cli save-on
|
||||
|
||||
|
||||
if retry 5 10s rcon-cli save-off; then
|
||||
# No matter what we were doing, from now on if the script crashes
|
||||
# or gets shut down, we want to make sure saving is on
|
||||
trap 'retry 5 5s rcon-cli save-on' EXIT
|
||||
|
||||
retry 5 10s rcon-cli save-all
|
||||
retry 5 10s sync
|
||||
|
||||
rcb backup
|
||||
|
||||
retry 20 10s rcon-cli save-on
|
||||
# Remove our exit trap now
|
||||
trap EXIT
|
||||
else
|
||||
log ERROR "Unable to turn saving off. Is the server running?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if (( PRUNE_BACKUPS_DAYS > 0 )); then
|
||||
rcb cleanup
|
||||
fi
|
|
@ -1,2 +1,2 @@
|
|||
10 2 * * * source /env.sh && rcb backup > /proc/1/fd/1
|
||||
10 2 * * * source /env.sh && /backup.sh > /proc/1/fd/1
|
||||
|
||||
|
|
Loading…
Reference in New Issue