diff --git a/Dockerfile b/Dockerfile index 6a26137..6a22f4c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,7 @@ RUN export DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND noninteractive RUN dpkg-divert --local --rename --add /sbin/initctl -RUN apt-get -y update; apt-get -y install gnupg2 wget ca-certificates rpl pwgen +RUN apt-get -y update; apt-get -y install gnupg2 wget ca-certificates rpl pwgen gdal-bin RUN sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ ${IMAGE_VERSION}-pgdg main" > /etc/apt/sources.list.d/postgresql.list' RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc -O- | apt-key add - @@ -31,6 +31,13 @@ ADD setup.sh /setup.sh RUN chmod +x /setup.sh RUN /setup.sh +ADD locale.gen /etc/locale.gen +RUN /usr/sbin/locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 +RUN update-locale ${LANG} + # We will run any commands in this when the container starts ADD docker-entrypoint.sh /docker-entrypoint.sh ADD setup-conf.sh / @@ -41,11 +48,4 @@ ADD setup-ssl.sh / ADD setup-user.sh / RUN chmod +x /docker-entrypoint.sh -ADD locale.gen /etc/locale.gen -RUN /usr/sbin/locale-gen -ENV LANG en_US.UTF-8 -ENV LANGUAGE en_US:en -ENV LC_ALL en_US.UTF-8 -RUN update-locale ${LANG} - ENTRYPOINT /docker-entrypoint.sh diff --git a/README.md b/README.md index 2ccab62..6b87cf8 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ differentiates itself by: * replication support included * Ability to create multiple database when you spin the database. * Enable multiple extensions in the database when setting it up +* Gdal drivers automatically registered for pg raster +* Support for out-of-db rasters We will work to add more security features to this container in the future with the aim of making a PostGIS image that is ready to be used in a production @@ -218,6 +220,14 @@ mirror database content from a designated master. This replication scheme allows us to sync databases. However a `replicant` is only for read-only transaction, thus we can't write new data to it. The whole database cluster will be replicated. +### Database permissions +Since we are using a role ${REPLICATION_USER}, we need to ensure that it has access to all +the tables in a particular schema. So if a user adds another schema called `data` +to the database `gis` he also has to update the permission for the user +with the following SQL assuming the ${REPLICATION_USER} is called replicator + + ALTER DEFAULT PRIVILEGES IN SCHEMA data GRANT SELECT ON TABLES TO replicator; + To experiment with the replication abilities, you can see a (docker-compose.yml)[sample/replication/docker-compose.yml] sample. There are several environment variables that you can set, such as: @@ -225,8 +235,8 @@ Master settings: - **ALLOW_IP_RANGE**: A pg_hba.conf domain format which will allow specified host(s) to connect into the container. This is needed to allow the `slave` to connect into `master`, so specifically this settings should allow `slave` address. It is also needed to allow clients on other hosts to connect to either the slave or the master. -- Both POSTGRES_USER and POSTGRES_PASS will be used as credentials for the slave to - connect, so make sure you change this into something secure. +- **REPLICATION_USER** Username to initiate streaming replication +- **REPLICATION_PASS** Password for a user with streaming replication role Slave settings: - **REPLICATE_FROM**: This should be the domain name or IP address of the `master` @@ -244,6 +254,8 @@ Slave settings: as `master` for a while. However, the promoted replicant will break consistencies and is not able to revert to replicant anymore, unless it is destroyed and resynced with the new master. +- **REPLICATION_USER** Username to initiate streaming replication +- **REPLICATION_PASS** Password for a user with streaming replication role To run the sample replication, follow these instructions: diff --git a/env-data.sh b/env-data.sh index e16d257..a848a74 100644 --- a/env-data.sh +++ b/env-data.sh @@ -2,6 +2,7 @@ DATADIR="/var/lib/postgresql/11/main" ROOT_CONF="/etc/postgresql/11/main" +PG_ENV="$ROOT_CONF/environment" CONF="$ROOT_CONF/postgresql.conf" WAL_ARCHIVE="/opt/archivedir" RECOVERY_CONF="$ROOT_CONF/recovery.conf" @@ -97,7 +98,9 @@ if [ -z "${POSTGRES_MULTIPLE_EXTENSIONS}" ]; then POSTGRES_MULTIPLE_EXTENSIONS='postgis,hstore,postgis_topology' fi - +if [ -z "${ALLOW_IP_RANGE}" ]; then + ALLOW_IP_RANGE='0.0.0.0/0' +fi if [ -z "${DEFAULT_ENCODING}" ]; then DEFAULT_ENCODING="UTF8" fi @@ -108,6 +111,13 @@ if [ -z "${DEFAULT_CTYPE}" ]; then DEFAULT_CTYPE="en_US.UTF-8" fi +if [ -z "${REPLICATION_USER}" ]; then + REPLICATION_USER=replicator +fi + +if [ -z "${REPLICATION_PASS}" ]; then + REPLICATION_PASS=replicator +fi # Compatibility with official postgres variable # Official postgres variable gets priority if [ ! -z "${POSTGRES_PASSWORD}" ]; then diff --git a/sample/replication/docker-compose.yml b/sample/replication/docker-compose.yml index 08c94f9..3ef57d9 100644 --- a/sample/replication/docker-compose.yml +++ b/sample/replication/docker-compose.yml @@ -22,8 +22,8 @@ services: ALLOW_IP_RANGE: '0.0.0.0/0' # We can specify optional credentials - POSTGRES_USER: 'docker' - POSTGRES_PASS: 'docker' + REPLICATION_USER: 'replicator' + REPLICATION_PASS: 'replicator' # Setup master replication variables #PG_MAX_WAL_SENDERS: 8 #PG_WAL_KEEP_SEGMENTS: 100 @@ -80,8 +80,8 @@ services: # For now we don't support different credentials for replication # so we use the same credentials as master's superuser, or anything that # have replication role. - POSTGRES_USER: 'docker' - POSTGRES_PASS: 'docker' + REPLICATION_USER: 'replicator' + REPLICATION_PASS: 'replicator' depends_on: pg-master: condition: service_healthy diff --git a/setup-database.sh b/setup-database.sh index d58f39d..ade92a1 100644 --- a/setup-database.sh +++ b/setup-database.sh @@ -47,7 +47,10 @@ source /setup-user.sh # Create a default db called 'gis' or $POSTGRES_DBNAME that you can use to get up and running quickly # It will be owned by the docker db user # Since we now pass a comma separated list in database creation we need to search for all databases as a test - +touch custom.sql +cat >> custom.sql <> ${ROOT_CONF}/pg_hba.conf + echo "Add rule to pg_hba: replication ${REPLICATION_USER} " + echo "host replication ${REPLICATION_USER} ${ALLOW_IP_RANGE} $authMethod" >> ${ROOT_CONF}/pg_hba.conf fi # Put lock file to make sure conf was not reinitialized diff --git a/setup-replication.sh b/setup-replication.sh index b4e034c..192427a 100755 --- a/setup-replication.sh +++ b/setup-replication.sh @@ -25,12 +25,12 @@ function configure_replication_permissions { echo "Setup data permissions" echo "----------------------" chown -R postgres:postgres $(getent passwd postgres | cut -d: -f6) - su - postgres -c "echo \"${REPLICATE_FROM}:${REPLICATE_PORT}:*:${POSTGRES_USER}:${POSTGRES_PASS}\" > ~/.pgpass" + su - postgres -c "echo \"${REPLICATE_FROM}:${REPLICATE_PORT}:*:${REPLICATION_USER}:${REPLICATION_PASS}\" > ~/.pgpass" su - postgres -c "chmod 0600 ~/.pgpass" } function streaming_replication { -until su - postgres -c "${PG_BASEBACKUP} -X stream -h ${REPLICATE_FROM} -p ${REPLICATE_PORT} -D ${DATADIR} -U ${POSTGRES_USER} -vP -w" +until su - postgres -c "${PG_BASEBACKUP} -X stream -h ${REPLICATE_FROM} -p ${REPLICATE_PORT} -D ${DATADIR} -U ${REPLICATION_USER} -vP -w --label=gis_pg_custer" do echo "Waiting for master to connect..." sleep 1s @@ -46,33 +46,19 @@ until su - postgres -c "${PG_BASEBACKUP} -X stream -h ${REPLICATE_FROM} -p ${REP if [[ "$DESTROY_DATABASE_ON_RESTART" =~ [Tt][Rr][Uu][Ee] ]]; then echo "Get initial database from master" - configure_replication_permissions - - streaming_replication - + if [ -f "${DATADIR}/backup_label.old" ]; then + echo "PG Basebackup already exists so proceed to start the DB" + else + streaming_replication + fi fi -#TODO We need a clever way to identify if base backup exists - Incoperate it as an else statement in destroy logic - - -#configure_replication_permissions -#var=`du -sh /var/lib/postgresql/11/main/pg_wal | awk '{print $1}'` -#var_size=${var:0:2} - -#if [[ "${var_size} -gt 33 " ]]; then - #echo ${var_size} - #echo "Base directory exist - Please startup the database" -#else - #echo "Base directory does not exists- Create a new one" - #streaming_replication -#fi - # Setup recovery.conf, a configuration file for slave cat > ${DATADIR}/recovery.conf < /tmp/PGPASSWORD.txt echo "postgresql password: $POSTGRES_PASS" >> /tmp/PGPASSWORD.txt # Check user already exists +echo "Creating superuser $POSTGRES_USER" RESULT=`su - postgres -c "psql postgres -t -c \"SELECT 1 FROM pg_roles WHERE rolname = '$POSTGRES_USER'\""` COMMAND="ALTER" if [ -z "$RESULT" ]; then COMMAND="CREATE" fi su - postgres -c "psql postgres -c \"$COMMAND USER $POSTGRES_USER WITH SUPERUSER ENCRYPTED PASSWORD '$POSTGRES_PASS';\"" + +echo "Creating replication user $REPLICATION_USER" +RESULT_REPLICATION=`su - postgres -c "psql postgres -t -c \"SELECT 1 FROM pg_roles WHERE rolname = '$REPLICATION_USER'\""` +COMMANDS="ALTER" +if [ -z "$RESULT_REPLICATION" ]; then + COMMANDS="CREATE" +fi +su - postgres -c "psql postgres -c \"$COMMANDS USER $REPLICATION_USER WITH REPLICATION ENCRYPTED PASSWORD '$REPLICATION_PASS';\"" +