Skip to content

Commit 615b950

Browse files
committed
Added weekly VACUUM FULL maintenance with cron scheduling for database optimization
openremote/openremote#1423
1 parent 18326e7 commit 615b950

File tree

4 files changed

+79
-4
lines changed

4 files changed

+79
-4
lines changed

Dockerfile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ ARG PG_MAJOR_PREVIOUS=14
33
ARG PG_MAJOR=15
44

55
FROM timescaledev/timescaledb-ha:pg15-multi as trimmed
6-
6+
LABEL maintainer="[email protected]"
77

88
USER root
99

10+
# Install cron for scheduled VACUUM FULL operations
11+
RUN apt-get update && apt-get install -y cron && rm -rf /var/lib/apt/lists/*
12+
1013
# Give postgres user the same UID and GID as the old alpine postgres image to simplify migration of existing DB
1114
RUN usermod -u 70 postgres \
1215
&& groupmod -g 70 postgres \

Dockerfile.alpine

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ FROM timescaledev/timescaledb-ha:pg15-multi as timescale-ha
2020
# This still doesn't work as timescale code is compiled against glibc and some references don't match with gcompat
2121

2222
FROM timescale/timescaledb:latest-pg15
23-
23+
LABEL maintainer="[email protected]"
2424

2525
ENV GLIBC_VERSION 2.35-r0
2626
ENV TZ ${TZ:-Europe/Amsterdam}
@@ -29,8 +29,8 @@ ENV POSTGRES_DB ${POSTGRES_DB:-openremote}
2929
ENV POSTGRES_USER ${POSTGRES_USER:-postgres}
3030
ENV POSTGRES_PASSWORD ${POSTGRES_PASSWORD:-postgres}
3131

32-
# Add glibc
33-
RUN apk add gcompat
32+
# Add glibc and cron for scheduled VACUUM FULL operations
33+
RUN apk add --no-cache gcompat dcron
3434

3535

3636
COPY --from=timescale-ha /usr/lib/postgresql/15/lib/bitcode/postgis-3/ /usr/local/lib/postgresql/bitcode/
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/bin/sh
2+
3+
# This script sets up a weekly VACUUM FULL job to clean up database bloat
4+
# VACUUM FULL reclaims more space than regular AUTOVACUUM by rewriting the entire table
5+
6+
# Create scripts directory if it doesn't exist
7+
mkdir -p /var/lib/postgresql/scripts
8+
9+
# Create the vacuum script that will run VACUUM FULL on all tables in the database
10+
cat > /var/lib/postgresql/scripts/vacuum_full.sh << 'EOF'
11+
#!/bin/sh
12+
13+
# Log file for vacuum operations
14+
LOG_FILE="/var/lib/postgresql/vacuum_full.log"
15+
16+
echo "$(date): Starting weekly VACUUM FULL operation" >> "$LOG_FILE"
17+
18+
# Get list of all tables in the database
19+
TABLES=$(psql -t -c "SELECT schemaname || '.' || tablename FROM pg_tables WHERE schemaname NOT IN ('pg_catalog', 'information_schema')" "${POSTGRES_DB:-postgres}")
20+
21+
# Run VACUUM FULL on each table
22+
for TABLE in $TABLES; do
23+
echo "$(date): Running VACUUM FULL on $TABLE" >> "$LOG_FILE"
24+
psql -c "VACUUM FULL $TABLE" "${POSTGRES_DB:-postgres}"
25+
echo "$(date): Completed VACUUM FULL on $TABLE" >> "$LOG_FILE"
26+
done
27+
28+
echo "$(date): Weekly VACUUM FULL operation completed" >> "$LOG_FILE"
29+
EOF
30+
31+
# Make the script executable
32+
chmod +x /var/lib/postgresql/scripts/vacuum_full.sh
33+
34+
# Set up cron job to run the script weekly (Sunday at 12:00 AM)
35+
CRON_ENTRY="0 0 * * 0 /var/lib/postgresql/scripts/vacuum_full.sh"
36+
37+
# Detect which cron system is available
38+
if command -v crond > /dev/null 2>&1; then
39+
# Alpine Linux (dcron)
40+
echo "Setting up cron job using Alpine's crond (dcron)..."
41+
mkdir -p /etc/crontabs
42+
echo "$CRON_ENTRY" > /etc/crontabs/postgres
43+
chmod 600 /etc/crontabs/postgres
44+
echo "Weekly VACUUM FULL job has been scheduled (Sundays at 12:00 AM) using dcron"
45+
46+
# Create a script to start crond when container starts
47+
cat > /var/lib/postgresql/scripts/start_cron.sh << 'EOF'
48+
#!/bin/sh
49+
if [ -x "$(command -v crond)" ]; then
50+
echo "Starting crond service for scheduled database maintenance..."
51+
crond -b -L /var/lib/postgresql/cron.log
52+
fi
53+
EOF
54+
chmod +x /var/lib/postgresql/scripts/start_cron.sh
55+
56+
elif command -v cron > /dev/null 2>&1; then
57+
# Debian/Ubuntu (standard cron)
58+
echo "Setting up cron job using standard cron..."
59+
(crontab -u postgres -l 2>/dev/null || echo "") | echo "$CRON_ENTRY" | crontab -u postgres -
60+
echo "Weekly VACUUM FULL job has been scheduled (Sundays at 12:00 AM) using standard cron"
61+
else
62+
echo "WARNING: No cron system found. VACUUM FULL will not be automatically scheduled."
63+
fi

or-entrypoint.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,4 +377,13 @@ if [ -n "$DATABASE_ALREADY_EXISTS" ]; then
377377
fi
378378
fi
379379

380+
# Start cron service if it exists (for scheduled VACUUM FULL operations)
381+
if [ -x "$(command -v cron)" ]; then
382+
echo "Starting cron service for scheduled database maintenance..."
383+
service cron start
384+
elif [ -x "$(command -v crond)" ] && [ -f "/var/lib/postgresql/scripts/start_cron.sh" ]; then
385+
echo "Starting Alpine crond service for scheduled database maintenance..."
386+
/var/lib/postgresql/scripts/start_cron.sh
387+
fi
388+
380389
exec /docker-entrypoint.sh $@

0 commit comments

Comments
 (0)