Linux Docker PostgreSQL ArcSDE Geodatabases

254
0
Thursday
Labels (2)
MarceloMarques
Esri Regular Contributor
3 0 254

_________________________________________________________________

docker-logo-blue.png

 


_________________________________________________________________

Running a Linux Docker container with PostgreSQL for the ArcSDE Geodatabase, while utilizing the Esri ST_Geometry library alongside PostGIS spatial data types, is an effective way to manage spatial data environments. This setup allows for enhanced functionality and optimized performance in geographic information systems (GIS) applications.
_________________________________________________________________

--1. Install Docker on Linux

Linux Docker Installation - Esri Community

_________________________________________________________________

--2. PostgreSQL on Docker

https://www.docker.com/blog/how-to-use-the-postgres-docker-official-image/

_________________________________________________________________
--2.1 docker postgresql image

docker pull postgres:15.13
docker pull postgres:16.9
docker pull postgres:16.8

docker image ls

_________________________________________________________________
--2.2 docker container postgresql

--create volume

docker volume ls
docker volume rm pg-db-16-data
docker volume create pg-db-16-data
docker volume rm pg-db-16-tbs
docker volume create pg-db-16-tbs

--NOTES:
--1. must follow the exactly order for the parameters or it fails to create the container!!!
--2. invalid value for parameter "port": "5437:5432"
--3. the -p option must come before the image name

Examples:

docker run --name pg-db-16 --restart=always \
-v c:/temp/my-postgres.conf:/etc/postgresql/postgresql.conf \
-e POSTGRES_PASSWORD="mcs7dmin" -p 5432:5432 \
-v pg-db-16-data:/var/lib/postgresql/data \
-d postgres:16.9 \
-c config_file=/etc/postgresql/postgresql.conf

docker run --name pg-db-16 --restart=always \
-v c:/temp/my-postgres.conf:/etc/postgresql/postgresql.conf \
-e POSTGRES_PASSWORD="mcs7dmin" -p 5437:5432 \
-v pg-db-16-data:/var/lib/postgresql/data \
-d postgres:16.9 \
-c config_file=/etc/postgresql/postgresql.conf

docker run --name pg-db-16 --restart=always \
-e POSTGRES_PASSWORD="mcs7dmin" -p 5432:5432 \
-v pg-db-16-data:/var/lib/postgresql/data \
-d postgres:16.9

docker run --name pg-db-16 --restart=always \
-e POSTGRES_PASSWORD="mcs7dmin" -p 5437:5432 \
-v pg-db-16-data:/var/lib/postgresql/data \
-d postgres:16.9

docker run --name pg-db-16 --restart=always \
-e POSTGRES_PASSWORD="mcs7dmin" -p 5437:5432 \
-v pg-db-16-data:/var/lib/postgresql/data \
-d postgres:16.8
docker volume rm pg-db-16-data
docker volume create pg-db-16-data
docker volume rm pg-db-16-tbs
docker volume create pg-db-16-tbs
docker run --name pg-db-16 --restart=always \
-e POSTGRES_PASSWORD="mcs7dmin" -p 5437:5432 \
-v pg-db-16-data:/var/lib/postgresql/data \
-v pg-db-16-tbs:/var/lib/postgresql/tbs
-d postgres:16.9

--(Optional): mount a host directory into the container for postgresql backups using -F d (directory option) for large databases

docker run --name pg-db-16 --restart=always \
-e POSTGRES_PASSWORD="mcs7dmin" -p 5437:5432 \
-v pg-db-16-data:/var/lib/postgresql/data \
-v pg-db-16-tbs:/var/lib/postgresql/tbs \
-v /dockerhome/postgresql/backups/pg-db-16/pg-dump:/var/lib/postgresql/backup \
-d postgres:16.8

docker run --name pg-db-16 --restart=always \
-e POSTGRES_PASSWORD="mcs7dmin" -p 5437:5432 \
-v pg-db-16-data:/var/lib/postgresql/data \
-v pg-db-16-tbs:/var/lib/postgresql/tbs \
-v /dockerhome/postgresql/backups/pg-db-16/pg-dump:/var/lib/postgresql/backup \
-d postgres:16.9

--set the permissions for the folders in the docker container

docker exec -it -u root pg-db-16 bash
chown -R postgres:postgres /var/lib/postgresql/backup
chown -R postgres:postgres /var/lib/postgresql/tbs
ls -la /var/lib/postgresql/
--Solution: Change Ownership from the Host
docker exec -it -u root pg-db-16 bash
whoami
--root
id -a postgres
--uid=999(postgres) gid=999(postgres) groups=999(postgres),101(ssl-cert)
exit

docker volume inspect pg-db-16-data
--"Mountpoint": "/dockerhome/dockerdata/volumes/pg-db-16-data/_data"

docker volume inspect pg-db-16-tbs
--"Mountpoint": "/dockerhome/dockerdata/volumes/pg-db-16-tbs/_data"

--Change ownership on the host
sudo chown -R 999:999 /dockerhome/dockerdata/volumes/pg-db-16-data/_data
sudo chown -R 999:999 /dockerhome/dockerdata/volumes/pg-db-16-tbs/_data
sudo chown -R 999:999 /dockerhome/postgresql/backups/pg-db-16/pg-dump

docker exec -it pg-db-16 bash
ls -la /var/lib/postgresql
exit

--check the docker container logs for errors.

docker logs --tail 50 pg-db-16

--list the docker containers

docker ps -a
docker inspect 5b72d963060b | grep IPAddress
IPAddress": "172.17.0.2"
docker port pg-db-16

docker logs pg-db-16
docker logs --tail 50 pg-db-16
docker logs -f pg-db-16
docker stop pg-db-16
docker start pg-db-16
docker restart pg-db-16

_________________________________________________________________
--2.3 docker container remove

docker stop pg-db-16
docker rm pg-db-16

_________________________________________________________________
--2.4 docker container upgrade from PostgreSQL 16.8 to PostgreSQL 16.9

--1. stop the container

docker stop pg-db-16

docker ps -a

--2. keep the docker volumes that were used to create the container

docker volume ls

--the volume pg-db-16-data has the PG instance configuration
--the volume pg-db-16-tbs has the PG databases tablespaces

--3. drop the old docker container running pg_16.8

docker rm pg-db-16
docker ps -a

--4. recreate the docker container using the pg_16.9 image

docker run --name pg-db-16 --restart=always \
-e POSTGRES_PASSWORD="mcs7dmin" -p 5437:5432 \
-v pg-db-16-data:/var/lib/postgresql/data \
-v pg-db-16-tbs:/var/lib/postgresql/tbs \
-v /dockerhome/postgresql/backups/pg-db-16/pg-dump:/var/lib/postgresql/backup \
-d postgres:16.9

docker ps -a

docker logs --tail 50 pg-db-16

--NOTES:
--a. using the same volumes, all the data will be preserved
--b. if you are upgrading a major new version (like 15 to 16),
-- PostgreSQL will automatically run any necessary data migration when it starts

--5. copy the esri st_geometry library to the docker container again

docker cp /dockerhome/esri_st_geom_lib/st_geometry.so 
pg-db-16:/usr/lib/postgresql/16/lib/st_geometry.so

docker exec -it pg-db-16 bash
chown root:root /usr/lib/postgresql/16/lib/st_geometry.so
ls -la /usr/lib/postgresql/16/lib/
exit

--6. set the permissions for the folders in the docker container

docker exec -it pg-db-16 bash
chown -R postgres:postgres /var/lib/postgresql/backup
chown -R postgres:postgres /var/lib/postgresql/tbs
ls -la /var/lib/postgresql/
exit

--7. install postgis extension again in the docker container

docker exec -it pg-db-16 bash
apt-get update
apt-get install postgresql-16-postgis-3
dpkg -l | grep postgis
exit

--8. upgrade the postgis extension in each postgresql database

MarceloMarques_1-1748637287347.png FAQ - Frequent Asked Questions
MarceloMarques_1-1748637287347.png How to Upgrade the PostgreSQL and PostGIS version for the Ent. Geodatabase on Windows
MarceloMarques_1-1748637287347.png How to Upgrade the PostgreSQL and PostGIS version for the Ent. Geodatabase on Linux
cd C:\Program Files\pgAdmin 4\runtime

psql -h ps026300 -p 5437 -U postgres -d postgres

\list

\c pm         <<-- connect to each pg database to upgrade the postgis extension

SELECT postgis_full_version();
ALTER EXTENSION postgis UPDATE;
SELECT postgis_extensions_upgrade();
ALTER EXTENSION postgis UPDATE;
SELECT postgis_full_version();

exit

_________________________________________________________________

--2.5 docker container psql

docker exec -it pg-db-16 psql -U postgres -d postgres -p 5432

_________________________________________________________________
--2.6 docker container terminal

docker exec -it pg-db-16 sh
docker exec -it pg-db-16 bash
docker exec -it -u root pg-db-16 bash
docker exec -it -u postgres pg-db-16 bash

_________________________________________________________________
--2.7 how to export a file from the docker container

docker cp pg-db-16:/var/lib/pgsql/data/pg_hba.conf 
/data/docker/postgres/16_9/pg_hba.conf

docker cp pg-db-16:/var/lib/pgsql/data/postgresql.conf
/data/docker/postgres/16_9/postgresql.conf

_________________________________________________________________

--2.8 how to copy a file to the docker container

docker cp /data/docker/postgres/16_9/pg_hba.conf 
pg-db-16:/var/lib/pgsql/data/pg_hba.conf

docker cp /data/docker/postgres/16_9/postgresql.conf
pg-db-16:/var/lib/pgsql/data/postgresql.conf
pg_hba.conf
#IPV4 local connections:
host all all 0.0.0.0/0 md5

_________________________________________________________________

--2.9 how to delete a file in the docker container

docker exec container_name rm -f /path/to/file.txt

docker exec pg-db-16 rm -f /var/lib/postgresql/data/pg_hba_5432.conf

_________________________________________________________________
--3. postgresql parameters

docker exec -it pg-db-16 psql -U postgres -d postgres -p 5432
--parameters
SELECT name, setting, unit, short_desc
FROM pg_settings
WHERE name = 'max_connections';

ALTER SYSTEM SET work_mem = '64MB';
ALTER SYSTEM SET max_connections = 1000;
SELECT pg_reload_conf();

exit;
docker run -d --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword postgres \
-c shared_buffers=256MB -c max_connections=200

docker run -d --name pg-db-16 -e POSTGRES_PASSWORD=mcs7dmin \
-c shared_buffers=256MB -c max_connections=200

docker run -d --name pg-db-16 -e POSTGRES_PASSWORD=mcs7dmin -c max_connections=10000

docker exec -it <container_name> psql -U <username> -d <database> \
-c "ALTER SYSTEM SET work_mem = '64MB';"

docker exec -it <container_name> psql -U <username> -d <database> \
-c "SELECT pg_reload_conf();"
docker stop pg-db-16
docker start pg-db-16
docker restart pg-db-16
Example:

docker exec -it pg-db-16 psql -U postgres -d postgres \
-c "ALTER SYSTEM SET max_connections = 7777;"

docker exec -it pg-db-16 psql -U postgres -d postgres -c "SELECT pg_reload_conf();"
--NOTE: does not refresh the parameter change
--it is necessary to stop/start the container!!!

docker restart pg-db-16

_________________________________________________________________
--4. postgresql tablespaces

docker exec -it pg-db-16 psql -U postgres -d postgres -p 5432

/db

SELECT spcname AS "Name",
pg_catalog.pg_get_userbyid(spcowner) AS "Owner",
pg_catalog.pg_tablespace_location(oid) AS "Location"
FROM pg_catalog.pg_tablespace;

exit;

_________________________________________________________________
--5. connect from remote machine

cd C:\Program Files\pgAdmin 4\runtime

psql --version

psql -h ps026300 -p 5437 -U postgres -d postgres

_________________________________________________________________
--6. COPY THE ESRI ST_GEOMETRY LIBRARY TO THE DOCKER CONTAINER

--docker container terminal
docker exec -it pg-db-16 sh
docker exec -it pg-db-16 bash

--where is postgresql installed

root@27fe7e13d0b9:/# which postgres
/usr/lib/postgresql/16/bin/postgres

--create the folder for the pg tablespaces of the geodatabases
mkdir -p /var/lib/postgresql/tbs
chown -R postgres:postgres /var/lib/postgresql/tbs

exit;

docker cp /dockerhome/esri_st_geom_lib/st_geometry.so
pg-db-16:/usr/lib/postgresql/16/lib/st_geometry.so

docker exec -it pg-db-16 bash
chown root:root /usr/lib/postgresql/16/lib/st_geometry.so
ls -la /usr/lib/postgresql/16/lib/
exit;

_________________________________________________________________
--7. HOW TO INSTALL POSTGIS IN A DOCKER CONTAINER

Option 1: Use the official PostGIS Docker image

postgis/postgis:16-3.5 is the image for PostgreSQL 16 with PostGIS 3.5.

You can verify the version tags here: https://hub.docker.com/r/postgis/postgis/tags

docker pull postgis/postgis:16-3.5
docker pull postgis/postgis:16-3.4

docker image ls

Option 2: Install PostGIS manually in a running container

docker exec -it pg-db-16 bash

_________________________________________________________________
--debian linux install package (docker container is debian linux !!!)

apt-get update

apt search postgis | grep postgresql-16 | sort
apt-cache madison postgis

apt-get install postgresql-16-postgis-3

apt list --installed | grep postgis

dpkg -l | grep postgis

exit

--how to install a specific postgis version

# apt search postgis | grep postgresql-16 | sort

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

debug symbols for postgresql-16-postgis-3
postgresql-16-mobilitydb/bookworm-pgdg 1.2.0-2.pgdg120+1 amd64
postgresql-16-pgrouting/bookworm-pgdg 3.8.0-1~exp1.pgdg120+1 amd64
postgresql-16-pgrouting-doc/bookworm-pgdg 3.7.0-1.pgdg120+1 all
postgresql-16-pgrouting-scripts/bookworm-pgdg 3.8.0-1~exp1.pgdg120+1 all
postgresql-16-postgis-3/bookworm-pgdg 3.5.3+dfsg-1~exp1.pgdg120+1 amd64
postgresql-16-postgis-3-dbgsym/bookworm-pgdg 3.5.3+dfsg-1~exp1.pgdg120+1 amd64
postgresql-16-postgis-3-scripts/bookworm-pgdg 3.5.3+dfsg-1~exp1.pgdg120+1 all
# apt-cache madison postgis
postgis | 3.5.3+dfsg-1~exp1.pgdg120+1 | http://apt.postgresql.org/pub/repos/apt bookworm-pgdg/main amd64 Packages
postgis | 3.3.2+dfsg-1+b1 | http://deb.debian.org/debian bookworm/main amd64 Packages
# apt-get install postgis=3.3.2+dfsg-1+b1
# apt list --installed | grep postgis

--debian linux how to remove a package

apt remove package-name
apt purge package-name
apt autoremove

or

dpkg -r package-name
dpkg --purge package-name

_________________________________________________________________

--8. Create the postgis extension in the PG database

docker exec -it your_container_name psql -U postgres -d your_database \
-c "CREATE EXTENSION postgis;"

TIP: To enable the PG geodatabase to support both spatial types: esri st_geometry and postgis, follow these steps:

  - Do not create the postgis extension in the database before creating the ArcSDE Repository.

  - First, create the ArcSDE Repository using the esri st_geometry option.

  - After the ArcSDE Repository is created, then add the postgis extension.

_________________________________________________________________

--9. PostgreSQL Geodatabase Best Practices

Use the database guide books and database templates scripts best practices to create the PostgreSQL Geodatabase.

 Mapping and Charting Solutions (MCS) Enterprise Databases Best Practices

*For Professional Database Administrators, requires advanced RDBMS and advanced Geodatabase experience.

_________________________________________________________________

--10. Docker Container PostgreSQL pg_dump backup

MarceloMarques_0-1748639276270.png How to Move the PostgreSQL Enterprise Geodatabase with pg_dump and pg_restore

The simplest way to back up a PostgreSQL database running in Docker is using pg_dump:

docker exec -t postgres-db pg_dump -U myuser mydatabase > backup.sql

To automate your backups, you can create a simple shell script and run it with cron:

#!/bin/bash
# pg_dump_bkp.sh
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_DIR="/tmp/pg_backups"

# Make sure the backup directory exists
mkdir -p $BACKUP_DIR

# Create the backup
docker exec postgres-db pg_dump -U myuser mydatabase | gzip > $BACKUP_DIR/postgres_$TIMESTAMP.sql.gz <-- SQL
docker exec postgres-db pg_dump -U myuser -F c -b -v mydatabase | gzip > $BACKUP_DIR/postgres_$TIMESTAMP.bkp.gz <-- DUMP

# Remove backups older than 30 days
find $BACKUP_DIR -name "postgres_*.sql.gz" -mtime +30 -delete

Make the script executable and run it:

chmod +x pg_dump_bkp.sh
bash pg_dump_bkp.sh

To fully automate the backup, you can add the script to your crontab to run daily:

0 3 * * * /path/to/pg_dump_bkp.sh

Example:

docker exec -t pg-db-16 pg_dump -U postgres pm > /dockerhome/postgresql/backups/pg-db-16/pg-dump/pg_bkp_pgdb169_pm.sql

docker exec -t pg-db-16 pg_dump -U postgres -F c -b -v pm > /dockerhome/postgresql/backups/pg-db-16/pg-dump/pg_bkp_pgdb169_pm.bkp
cd /dockerhome/postgresql/scripts

cat pg_dump_bkp.sh
----------------
#!/bin/bash
# Usage: ./pg_dump_bkp.sh <container_name> <database_name>

# Check for required arguments
if [ $# -ne 2 ]; then
echo "Usage: $0 <docker_container_name> <database_name>"
exit 1
fi

CONTAINER_NAME="$1"
DATABASE_NAME="$2"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_DIR="/dockerhome/postgresql/backups/${CONTAINER_NAME}/pg-dump/${DATABASE_NAME}"
#--(Optional): mount a host directory into the container for postgresql backups using -F d (directory option) for large databases
BACKUP_DIR2="/var/lib/postgresql/backup/${DATABASE_NAME}"

# Make sure the backup directory exists
#mkdir -p "$BACKUP_DIR"

# Create the backup
#--docker exec "$CONTAINER_NAME" pg_dump -U postgres -F c -b -v "$DATABASE_NAME" | gzip > "$BACKUP_DIR/pg_bkp_${CONTAINER_NAME}_${DATABASE_NAME}_$TIMESTAMP.bkp.gz"

#--(Optional): mount a host directory into the container for postgresql backups using -F d (directory option) for large databases
docker exec "$CONTAINER_NAME" pg_dump -U postgres -F c -b -v -f "$BACKUP_DIR2/pg_bkp_${CONTAINER_NAME}_${DATABASE_NAME}_$TIMESTAMP.bkp" "$DATABASE_NAME"

gzip "$BACKUP_DIR/pg_bkp_${CONTAINER_NAME}_${DATABASE_NAME}_$TIMESTAMP.bkp"

# Remove backups older than 30 days
find "$BACKUP_DIR" -name "pg_bkp_${CONTAINER_NAME}_${DATABASE_NAME}_*.bkp.gz" -mtime +30 -delete

---------------

chmod +x ./pg_dump_bkp.sh

./pg_dump_bkp.sh pg-db-16 pm

--extract the backup from gzip file
gzip -d $BACKUP_DIR/pg_bkp_pgdb169_pm_$TIMESTAMP.bkp.gz

--The reason you cannot perform a pg_dump -F d (directory format) backup and copy it to the host in one step is due to
--how the directory format works and how Docker handles file I/O.

cd /dockerhome/postgresql/scripts
cat pg_dump_bkp_dir.sh
---------------
#!/bin/bash
# Usage: ./pg_dump_bkp_dir.sh <container_name> <database_name>

# Check if both container name and database name are provided
if [ -z "$1" ] || [ -z "$2" ]; then
echo "Usage: $0 <container_name> <db_name>"
exit 1
fi

# Configuration
CONTAINER_NAME="$1"
DB_NAME="$2"
DB_USER="postgres"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
CONTAINER_BACKUP_DIR="/var/lib/postgresql/data/backups/pg_bkp_${CONTAINER_NAME}_${DB_NAME}_${TIMESTAMP}"
HOST_BACKUP_DIR="/dockerhome/postgresql/backups/${CONTAINER_NAME}/pg-dump/${DATABASE_NAME}/pg_bkp_${CONTAINER_NAME}_${DB_NAME}_${TIMESTAMP}"

# Step 1: Create backup directory inside container
docker exec -t "$CONTAINER_NAME" mkdir -p "$CONTAINER_BACKUP_DIR"

# Step 2: Run pg_dump in directory format
docker exec -t "$CONTAINER_NAME" pg_dump -U "$DB_USER" -F d -j 16 -b -v -f "$CONTAINER_BACKUP_DIR" "$DB_NAME"

# Step 3: Copy backup from container to host
docker cp "$CONTAINER_NAME":"$CONTAINER_BACKUP_DIR" "$HOST_BACKUP_DIR"

# Step 4: Remove backup directory from container
docker exec -t "$CONTAINER_NAME" rm -rf "$CONTAINER_BACKUP_DIR"

echo "Backup completed and copied to host. Container backup directory cleaned up."
---------------
chmod +x pg_dump_bkp_dir.sh

./pg_dump_bkp_dir.sh pg-db-16 pm

Alternative (Advanced)

If you want to avoid copying, you could mount a host directory into the container using Docker volumes:

docker run -v /host/backup/dir:/container/backup/path ...

Then run pg_dump -F d -f /container/backup/path — this way, the backup is written directly to the host.

Step by step:

Step 1: Create a Host Directory for Backups

Choose or create a directory on your host where you want the backups to be stored:

mkdir -p /dockerhome/postgresql/backups/pg-db-16/pg-dump

Step 2: Run the PostgreSQL Container with a Volume Mount

When starting your PostgreSQL container, mount the host directory into the container using the -v flag:

docker run -d \
--name pg-db-16 \
-e POSTGRES_PASSWORD=yourpassword \
-v /dockerhome/postgresql/backups/pg-db-16/pg-dump:/var/lib/postgresql/backup \
postgres:16

This mounts the host directory to /var/lib/postgresql/backup inside the container.

If your container is already running, you’ll need to recreate it with the volume mount, as Docker doesn’t allow modifying volumes on a running container.

Step 3: Run pg_dump to the Mounted Volume

Now, inside the container, you can run:

docker exec -t pg-db-16 pg_dump -U postgres -F d -j 16 -b -v -f /var/lib/postgresql/backup/pg_bkp_pm pm

This will create a directory-format backup directly in your host’s mounted folder:

/dockerhome/postgresql/backups/pg-db-16/pg-dump/pg_bkp_pm/

cd /dockerhome/postgresql/scripts
cat pg_dump_bkp_dir.sh
----------------
#!/bin/bash
# Usage: ./pg_dump_bkp_dir.sh <container_name> <database_name>

# Check for required arguments
if [ $# -ne 2 ]; then
echo "Usage: $0 <docker_container_name> <database_name>"
exit 1
fi

CONTAINER_NAME="$1"
DATABASE_NAME="$2"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_DIR="/dockerhome/postgresql/backups/${CONTAINER_NAME}/pg-dump/${DATABASE_NAME}"
BACKUP_FOLDER="pg_bkp_${CONTAINER_NAME}_${DATABASE_NAME}_${TIMESTAMP}_bkp"
# mount a host directory into the container for postgresql backups using -F d (directory option) for large databases
CONTAINER_BACKUP_DIR="/var/lib/postgresql/backup/${DATABASE_NAME}/${BACKUP_FOLDER}"

# Make sure the backup directory exists
#mkdir -p "$BACKUP_DIR"
#mkdir -p "$BACKUP_FOLDER"

# Create the backup

docker exec "$CONTAINER_NAME" pg_dump -U postgres -F d -j 16 -b -w -f "$CONTAINER_BACKUP_DIR" "$DATABASE_NAME"

tar -czvf "$BACKUP_DIR"/"$BACKUP_FOLDER".tar.gz -C "$BACKUP_DIR" "$BACKUP_FOLDER"

rm -rf "$BACKUP_DIR"/"$BACKUP_FOLDER"

# Remove backups older than 30 days
DAYS_TO_KEEP=30
find "$BACKUP_DIR" -name "pg_bkp_${CONTAINER_NAME}_${DATABASE_NAME}_*_bkp.tar.gz" -mtime +$DAYS_TO_KEEP -delete
find $BACKUP_DIR -type d -mtime +$DAYS_TO_KEEP -name "*" -exec rm -rf '{}' ';'

---------------
chmod +x pg_dump_bkp_dir.sh

./pg_dump_bkp_dir.sh pg-db-16 pm

How to extract
tar -xzvf mydata.tar.gz

_________________________________________________________________
--11. Docker Container PostgreSQL pg_restore

 MarceloMarques_0-1748560371644.png How to Move the PostgreSQL Enterprise Geodatabase with pg_dump and pg_restore
To restore a PostgreSQL database using pg_restore within a Docker container, you typically follow these steps:
 
Step-by-Step Instructions
 
1. Copy the backup file into the container (optional)
 
If your backup file is on the host machine:
 
docker cp my_backup.dump my_postgres:/my_backup.dump
2. Run pg_restore inside the container
 
You can execute pg_restore using docker exec:
 
docker exec -i my_postgres pg_restore \
-U postgres \
  -d my_database \
  -v /my_backup.dump
-U postgres: PostgreSQL user
-d my_database: Target database name
-v: Verbose output
/my_backup.dump: Path to the backup file inside the container
 
If the database doesn't exist yet, you can create it first:
 
docker exec -i my_postgres createdb -U postgres my_database
Alternative: Pipe from host
 
If you don’t want to copy the file into the container:
 
cat my_backup.dump | docker exec -i my_postgres pg_restore \
  -U postgres \
  -d my_database \
  -v
Step-by-step Example:
 
--Restore each schema, follow this order: public,sde,pm,raster,pmeditor,pmviewer
 
--Restore public
docker exec -i pg-db-16 pg_restore -U postgres -d pm \
-n public < /dockerhome/postgresql/backups/pg-db-16/pg-dump/pg_bkp_pg-db-16_pm_20250520.bkp
pg_restore: error: could not execute query: ERROR:  
relation "sde.sde_coordinate_systems" does not exist
Command was:
ALTER TABLE ONLY public.sde_spatial_references
    ADD CONSTRAINT spatial_ref_fk1 FOREIGN KEY (cs_id)
REFERENCES sde.sde_coordinate_systems(id);
docker exec -it pg-db-16 psql -U postgres -d postgres -p 5432

ALTER TABLE ONLY public.sde_spatial_references
    ADD CONSTRAINT spatial_ref_fk1 FOREIGN KEY (cs_id)
REFERENCES sde.sde_coordinate_systems(id);

Note: import sde backup then recreate the constraint!!!
--Restore sde
docker exec -i pg-db-16 pg_restore -U postgres -d pm \
-n sde < /dockerhome/postgresql/backups/pg-db-16/pg-dump/pg_bkp_pg-db-16_pm_20250520.bkp
docker exec -it pg-db-16 psql -U postgres -d postgres -p 5432

psql -h ps026300 -p 5437 -U postgres -d postgres
\c pm
ALTER TABLE ONLY public.sde_spatial_references
ADD CONSTRAINT spatial_ref_fk1
FOREIGN KEY (cs_id) REFERENCES sde.sde_coordinate_systems(id);
--Restore pm
docker exec -i pg-db-16 pg_restore -U postgres -d pm \
-n pm < /dockerhome/postgresql/backups/pg-db-16/pg-dump/pg_bkp_pg-db-16_pm_20250520.bkp
--Restore raster
docker exec -i pg-db-16 pg_restore -U postgres -d pm \
-n raster < /dockerhome/postgresql/backups/pg-db-16/pg-dump/pg_bkp_pg-db-16_pm_20250520.bkp
--Restore pmeditor
 
docker exec -i pg-db-16 pg_restore -U postgres -d pm \
-n pmeditor < /dockerhome/postgresql/backups/pg-db-16/pg-dump/pg_bkp_pg-db-16_pm_20250520.bkp
--Restore pmviewer
docker exec -i pg-db-16 pg_restore -U postgres -d pm \
-n pmviewer < /dockerhome/postgresql/backups/pg-db-16/pg-dump/pg_bkp_pg-db-16_pm_20250520.bkp
psql -h ps026300 -p 5437 -U postgres -d postgres

--Update search_path to public,sde otherwise will fail to draw the data
ALTER DATABASE pm SET search_path="$user", public, sde;
GRANT ALL ON DATABASE pm TO public;
GRANT ALL ON DATABASE pm TO postgres;
_________________________________________________________________

--12. Docker Container PostgreSQL database maintenance

Here's a shell script that performs PostgreSQL maintenance (VACUUM, REINDEX, and ANALYZE) inside a Docker container.

It accepts the container name and database name as input arguments and uses a .sql file from the host machine to execute the commands via psql.

Accepts the container name, database name, and SQL file path as arguments.
Saves the output of the maintenance commands to a .log file.
Stores the log file in a logs/ directory on the host machine, creating it if it doesn't exist.

--------------------------------------------
Script: pg_db_maintenance.sh

#!/bin/bash

# Usage: ./pg_maintenance.sh <container_name> <database_name> <path_to_sql_file>

CONTAINER_NAME="$1"
DATABASE_NAME="$2"
SQL_FILE="$3"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOG_DIR="./logs"
LOG_FILE="$LOG_DIR/maintenance_${CONTAINER_NAME}_${DATABASE_NAME}_${TIMESTAMP}.log"

# Validate input
if [[ -z "$CONTAINER_NAME" || -z "$DATABASE_NAME" || -z "$SQL_FILE" ]]; then
echo "Usage: $0 <container_name> <database_name> <path_to_sql_file>"
exit 1
fi

# Create logs directory if it doesn't exist
mkdir -p "$LOG_DIR"

# Run the SQL maintenance commands and log the output
echo "Running maintenance on database '$DATABASE_NAME' in container '$CONTAINER_NAME'..."
docker exec -i "$CONTAINER_NAME" psql -U postgres -d "$DATABASE_NAME" < "$SQL_FILE" &> "$LOG_FILE"

echo "Maintenance completed. Log saved to: $LOG_FILE"

--------------------------------------------
Example SQL File: pg_db_maintenance.sql

VACUUM FULL;
REINDEX DATABASE;
ANALYZE;

--------------------------------------------
Replace current_database with your actual database name or use SELECT current_database(); inside the SQL if needed.
--------------------------------------------
How to Use
1. Save the script as pg_maintenance.sh and make it executable:
chmod +x pg_db_maintenance.sh
2. Create your pg_db_maintenance.sql file with the desired commands.
3. Run the script:
./pg_maintenance.sh my_postgres_container my_database /path/to/maintenance.sql
--------------------------------------------

To fully automate the backup, you can add the script to your crontab to run daily:

0 3 * * * /path/to/pg_db_maintenance.sh my_postgres_container my_database /path/to/pg_db_maintenance.sql

------------------------------------------------------------------------------------------------------------------------------------

Examples:

cd /dockerhome/postgresql/scripts

./pg_db_maintenance.sh pg-db-16 agmgdbpg pg_db_maintenance.sql


--Manual Examples:

--A:

docker exec -i pg-db-16 psql -U postgres \
-d agmgdbpg < pg_db_maintenance.sql &> ./logs/maintenance_pg-db-16_agmgdbpg_20250523.log

--B:

docker exec -it pg-db-16 psql -U postgres -d agmgdbpg -p 5432
VACUUM FULL;
REINDEX DATABASE;
ANALYZE;
\quit
_________________________________________________________________

 

Contributors
About the Author
| Marcelo Marques | Esri Principal Product Engineer | Cloud & Database Administrator | OCP - Oracle Database Certified Professional | 32 years' experience | www.linkedin.com/in/mmarquesbr | "I embarked on my journey with Esri Technology in 1992, and since 1997, I have been working with ArcSDE Geodatabases, right from its initial release." | " a successful Enterprise ArcGIS application deployment starts with a strong physical database design and best database administration practices" | " I do not fear computers. I fear the lack of them." - Isaac Asimov |