From 9fff5cef23ffe770901241ea98af80e8922d19d0 Mon Sep 17 00:00:00 2001 From: Bram Date: Wed, 21 May 2025 21:06:41 +0200 Subject: [PATCH] postgres shadow --- Dockers/postgres-shadow/Dockerfile | 25 +++++++- Dockers/postgres-shadow/docker-entrypoint.sh | 14 +++++ Dockers/postgres-shadow/init.sh | 25 -------- Dockers/postgres-shadow/refresh.sh | 64 ++++++++++++++++++++ Dockers/postgres-shadow/version | 1 + 5 files changed, 103 insertions(+), 26 deletions(-) create mode 100644 Dockers/postgres-shadow/docker-entrypoint.sh delete mode 100644 Dockers/postgres-shadow/init.sh create mode 100644 Dockers/postgres-shadow/refresh.sh create mode 100644 Dockers/postgres-shadow/version diff --git a/Dockers/postgres-shadow/Dockerfile b/Dockers/postgres-shadow/Dockerfile index 3f81ea3..00179de 100644 --- a/Dockers/postgres-shadow/Dockerfile +++ b/Dockers/postgres-shadow/Dockerfile @@ -1,8 +1,9 @@ -FROM postgres:15 +FROM pgvector/pgvector:pg15 # Install additional tools RUN apt-get update && apt-get install -y \ postgresql-client \ + cron \ && rm -rf /var/lib/apt/lists/* # Create directory for scripts @@ -12,9 +13,31 @@ RUN mkdir -p /docker-entrypoint-initdb.d COPY init.sh /docker-entrypoint-initdb.d/ RUN chmod +x /docker-entrypoint-initdb.d/init.sh +# Copy refresh script +COPY refresh.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/refresh.sh + # Environment variables ENV SOURCE_DB_URL="" ENV TARGET_DB_NAME="shadow_db" +ENV TARGET_DB_USER="postgres" +ENV TARGET_DB_PASSWORD="" +ENV REFRESH_TIME="00:00" + +# Define volume for persistent data +VOLUME ["/var/lib/postgresql/data"] # Expose PostgreSQL port EXPOSE 5432 + +# Add crontab file +RUN echo "0 0 * * * /usr/local/bin/refresh.sh >> /var/log/cron.log 2>&1" > /etc/cron.d/refresh-cron +RUN chmod 0644 /etc/cron.d/refresh-cron + +# Create the log file to be able to run tail +RUN touch /var/log/cron.log + +# Start cron and PostgreSQL +COPY docker-entrypoint.sh / +RUN chmod +x /docker-entrypoint.sh +ENTRYPOINT ["/docker-entrypoint.sh"] diff --git a/Dockers/postgres-shadow/docker-entrypoint.sh b/Dockers/postgres-shadow/docker-entrypoint.sh new file mode 100644 index 0000000..cbe71e1 --- /dev/null +++ b/Dockers/postgres-shadow/docker-entrypoint.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e + +# Start cron +service cron start + +# Update crontab with the specified refresh time +hour=$(echo $REFRESH_TIME | cut -d':' -f1) +minute=$(echo $REFRESH_TIME | cut -d':' -f2) +echo "$minute $hour * * * /usr/local/bin/refresh.sh >> /var/log/cron.log 2>&1" > /etc/cron.d/refresh-cron +chmod 0644 /etc/cron.d/refresh-cron + +# Start PostgreSQL +exec docker-entrypoint.sh postgres \ No newline at end of file diff --git a/Dockers/postgres-shadow/init.sh b/Dockers/postgres-shadow/init.sh deleted file mode 100644 index dd5c13b..0000000 --- a/Dockers/postgres-shadow/init.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -set -e - -# Wait for PostgreSQL to be ready -until pg_isready; do - echo "Waiting for PostgreSQL to be ready..." - sleep 2 -done - -# Create the target database -psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL - CREATE DATABASE $TARGET_DB_NAME; -EOSQL - -# Copy the database if SOURCE_DB_URL is provided -if [ ! -z "$SOURCE_DB_URL" ]; then - echo "Copying database from $SOURCE_DB_URL to $TARGET_DB_NAME..." - - # Dump the source database - pg_dump "$SOURCE_DB_URL" | psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$TARGET_DB_NAME" - - echo "Database copy completed successfully" -else - echo "No SOURCE_DB_URL provided, skipping database copy" -fi \ No newline at end of file diff --git a/Dockers/postgres-shadow/refresh.sh b/Dockers/postgres-shadow/refresh.sh new file mode 100644 index 0000000..a609a76 --- /dev/null +++ b/Dockers/postgres-shadow/refresh.sh @@ -0,0 +1,64 @@ +#!/bin/bash +set -e + +echo "Starting database refresh at $(date)" + +# Wait for PostgreSQL to be ready +until pg_isready; do + echo "Waiting for PostgreSQL to be ready..." + sleep 2 +done + +# Create user if it doesn't exist +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + DO + \$do\$ + BEGIN + IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '$POSTGRES_USER') THEN + CREATE USER $POSTGRES_USER WITH PASSWORD '$POSTGRES_PASSWORD' SUPERUSER; + END IF; + END + \$do\$; +EOSQL + +# Drop and recreate the target database +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + DROP DATABASE IF EXISTS $TARGET_DB_NAME; + CREATE DATABASE $TARGET_DB_NAME OWNER $POSTGRES_USER; +EOSQL + +# Copy the database if SOURCE_DB_URL is provided +if [ ! -z "$SOURCE_DB_URL" ]; then + echo "Copying database from $SOURCE_DB_URL to $TARGET_DB_NAME..." + + # Dump the source database and filter out transaction_timeout + pg_dump "$SOURCE_DB_URL" | grep -v "transaction_timeout" | psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$TARGET_DB_NAME" + + # Update ownership of all objects + psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$TARGET_DB_NAME" <<-EOSQL + DO \$\$ + DECLARE + r record; + BEGIN + FOR r IN SELECT tablename FROM pg_tables WHERE schemaname = 'public' + LOOP + EXECUTE 'ALTER TABLE public.' || quote_ident(r.tablename) || ' OWNER TO $POSTGRES_USER'; + END LOOP; + + FOR r IN SELECT sequence_name FROM information_schema.sequences WHERE sequence_schema = 'public' + LOOP + EXECUTE 'ALTER SEQUENCE public.' || quote_ident(r.sequence_name) || ' OWNER TO $POSTGRES_USER'; + END LOOP; + + FOR r IN SELECT typname FROM pg_type WHERE typnamespace = 'public'::regnamespace + LOOP + EXECUTE 'ALTER TYPE public.' || quote_ident(r.typname) || ' OWNER TO $POSTGRES_USER'; + END LOOP; + END + \$\$; +EOSQL + + echo "Database refresh completed successfully at $(date)" +else + echo "No SOURCE_DB_URL provided, skipping database refresh" +fi \ No newline at end of file diff --git a/Dockers/postgres-shadow/version b/Dockers/postgres-shadow/version new file mode 100644 index 0000000..b9bc2fd --- /dev/null +++ b/Dockers/postgres-shadow/version @@ -0,0 +1 @@ +latest \ No newline at end of file