From 7335fb60916c4133bac34f9d9b3b917faca36bea Mon Sep 17 00:00:00 2001 From: Emanuele Scarsella Date: Thu, 28 Nov 2024 12:07:28 +0100 Subject: [PATCH 1/3] Added feature: it's now possible to define custom username and password for each database. --- create-multiple-postgresql-databases.sh | 78 +++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 6 deletions(-) diff --git a/create-multiple-postgresql-databases.sh b/create-multiple-postgresql-databases.sh index aa665fa..ea1610b 100755 --- a/create-multiple-postgresql-databases.sh +++ b/create-multiple-postgresql-databases.sh @@ -1,16 +1,82 @@ #!/bin/bash +# +# Source: https://github.com/mrts/docker-postgresql-multiple-databases +# Author: Mart Sõmermaa (https://github.com/mrts) +# contributor: Jens Peter Secher (https://github.com/jpsecher) +# contributor: Emanuele Scarsella (https://github.com/emanuele-scarsella) +# License: MIT +# set -e set -u function create_user_and_database() { local database=$1 - echo " Creating user and database '$database'" - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL - CREATE USER $database; - CREATE DATABASE $database; - GRANT ALL PRIVILEGES ON DATABASE $database TO $database; -EOSQL + local user=$(get_user_for_database $database) + local password=$(get_password_for_database $database) + if user_exists $user; then + echo "User '$user' already exists, skipping" + else + echo "Creating user '$user' ${password:+(with password)}" + create_user $user $password + fi + if database_exists $database; then + echo "Database '$database' already exists, skipping" + else + echo "Creating database '$database' and granting all privileges to user '$user'" + create_database $database $user + fi +} + +function create_user() { + local user=$1 + local password=$2 + psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE USER "$user" ${password:+WITH PASSWORD '$password'}; + EOSQL +} + +function create_database() { + local database=$1 + local user=$2 + psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE "$database" WITH OWNER "$user"; + GRANT ALL PRIVILEGES ON DATABASE "$database" TO "$user"; + EOSQL +} + +function user_exists() { + local user=$1 + local result + result=$(psql -t -v ON_ERROR_STOP=1 \ + --username "$POSTGRES_USER" \ + --dbname "$POSTGRES_DB" \ + -c "SELECT 1 FROM pg_roles WHERE rolname = '$user';") + if [[ "$result" =~ 1 ]]; then + return 0 + fi + return 1 +} + +function database_exists() { + local database="$1" + if psql -lqt --username "$POSTGRES_USER" | cut -d \| -f 1 | grep -qw "$database"; then + return 0 + else + return 1 + fi +} + +function get_user_for_database() { + local database=$1 + local user_var="POSTGRES_USER_${database^^}" + echo "${!user_var:-$database}" +} + +function get_password_for_database() { + local database=$1 + local password_var="POSTGRES_PASSWORD_${database^^}" + echo "${!password_var:-}" } if [ -n "$POSTGRES_MULTIPLE_DATABASES" ]; then From ef833413999dcf1d2db8e991cd523243e4961feb Mon Sep 17 00:00:00 2001 From: Emanuele Scarsella Date: Thu, 28 Nov 2024 12:10:08 +0100 Subject: [PATCH 2/3] Added documentation for custom user definition. --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index d4b6a15..e84e065 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,24 @@ to the container: - POSTGRES_USER: myapp - POSTGRES_PASSWORD: +### Custom user and password for each database + +If you need to use a custom user and password for each database, you can do it by adding the `POSTGRES_USER_` +and `POSTGRES_PASSWORD_` environment variables: + + myapp-postgresql: + image: postgres:9.6.2 + volumes: + - ../docker-postgresql-multiple-databases:/docker-entrypoint-initdb.d + environment: + - POSTGRES_MULTIPLE_DATABASES: db1,db2 + - POSTGRES_USER: myapp + - POSTGRES_PASSWORD: + - POSTGRES_USER_DB1: myapp_db1 + - POSTGRES_PASSWORD_DB1: + - POSTGRES_USER_DB2: myapp_db2 + - POSTGRES_PASSWORD_DB2: + ### Non-standard database names If you need to use non-standard database names (hyphens, uppercase letters etc), quote them in `POSTGRES_MULTIPLE_DATABASES`: From 173a1125d516b0325a5c8a585f4f6f58906547c1 Mon Sep 17 00:00:00 2001 From: Emanuele Scarsella Date: Thu, 28 Nov 2024 12:12:43 +0100 Subject: [PATCH 3/3] Added comments to make the code easier to understand. --- create-multiple-postgresql-databases.sh | 32 +++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/create-multiple-postgresql-databases.sh b/create-multiple-postgresql-databases.sh index ea1610b..68ac154 100755 --- a/create-multiple-postgresql-databases.sh +++ b/create-multiple-postgresql-databases.sh @@ -10,6 +10,9 @@ set -e set -u +# Create a user and a database, if they don't already exist +# Arguments: +# $1 - Database name function create_user_and_database() { local database=$1 local user=$(get_user_for_database $database) @@ -28,6 +31,10 @@ function create_user_and_database() { fi } +# Create a PostgreSQL user +# Arguments: +# $1 - User name +# $2 - User password (optional) function create_user() { local user=$1 local password=$2 @@ -36,6 +43,10 @@ function create_user() { EOSQL } +# Create a PostgreSQL database and assign ownership +# Arguments: +# $1 - Database name +# $2 - User name function create_database() { local database=$1 local user=$2 @@ -45,6 +56,11 @@ function create_database() { EOSQL } +# Check if a PostgreSQL user exists +# Arguments: +# $1 - User name +# Returns: +# 0 if user exists, 1 otherwise function user_exists() { local user=$1 local result @@ -58,6 +74,11 @@ function user_exists() { return 1 } +# Check if a PostgreSQL database exists +# Arguments: +# $1 - Database name +# Returns: +# 0 if database exists, 1 otherwise function database_exists() { local database="$1" if psql -lqt --username "$POSTGRES_USER" | cut -d \| -f 1 | grep -qw "$database"; then @@ -67,18 +88,29 @@ function database_exists() { fi } +# Retrieve the user for a given database +# Arguments: +# $1 - Database name +# Returns: +# User name derived from environment variables or defaults to database name function get_user_for_database() { local database=$1 local user_var="POSTGRES_USER_${database^^}" echo "${!user_var:-$database}" } +# Retrieve the password for a given database +# Arguments: +# $1 - Database name +# Returns: +# Password derived from environment variables or empty if not set function get_password_for_database() { local database=$1 local password_var="POSTGRES_PASSWORD_${database^^}" echo "${!password_var:-}" } +# Main script logic: Create multiple databases if specified in the environment variable if [ -n "$POSTGRES_MULTIPLE_DATABASES" ]; then echo "Multiple database creation requested: $POSTGRES_MULTIPLE_DATABASES" for db in $(echo $POSTGRES_MULTIPLE_DATABASES | tr ',' ' '); do