-
Notifications
You must be signed in to change notification settings - Fork 0
Add replication capabilities #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,12 @@ | ||
| # Copyright (c) 2026 Alexander Todorov <atodorov@otb.bg> | ||
| # | ||
| # Licensed under GNU Affero General Public License v3 or later (AGPLv3+) | ||
| # https://www.gnu.org/licenses/agpl-3.0.html | ||
|
|
||
| FROM postgres:17@sha256:e38411452a464af89e5adadb8d223bf53b898d47d6ef918b2d58c08707350449 | ||
|
|
||
| COPY ./docker-entrypoint-initdb.d/00_enable_ssl.sh /docker-entrypoint-initdb.d/ | ||
|
|
||
| COPY entrypoint.sh /usr/local/bin/ | ||
| ENTRYPOINT ["entrypoint.sh"] | ||
| CMD ["postgres"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| # Copyright (c) 2026 Alexander Todorov <atodorov@otb.bg> | ||
| # | ||
| # Licensed under GNU Affero General Public License v3 or later (AGPLv3+) | ||
| # https://www.gnu.org/licenses/agpl-3.0.html | ||
|
|
||
| echo "INFO: check if replication is configured" | ||
| if [ ! -s "$PGDATA/PG_VERSION" ] && [ -n "$POSTGRES_REPLICATION_USER" ]; then | ||
| mkdir -p "$PGDATA" | ||
| chmod 00700 "$PGDATA" || : | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because this block runs before |
||
|
|
||
| if [ -z "$POSTGRES_REPLICATION_PASSWORD" ]; then | ||
| echo "ERROR: POSTGRES_REPLICATION_PASSWORD is undefined" | ||
| exit 1 | ||
| fi | ||
|
|
||
| if [ -z "$POSTGRES_PRIMARY_HOST" ]; then | ||
| echo "ERROR: POSTGRES_PRIMARY_HOST is undefined" | ||
| exit 2 | ||
| fi | ||
|
|
||
| echo "INFO: starting initial wal sync" | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| pg_basebackup \ | ||
| --dbname "postgres://$POSTGRES_REPLICATION_USER:$POSTGRES_REPLICATION_PASSWORD@$POSTGRES_PRIMARY_HOST/postgres?sslmode=require" \ | ||
| --pgdata "$PGDATA" \ | ||
| --progress --verbose --write-recovery-conf --wal-method stream \ | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using |
||
| --create-slot --slot "$POSTGRES_REPLICATION_USER" | ||
|
|
||
| echo "INFO: completed initial wal sync" | ||
| fi | ||
|
|
||
| echo "INFO: starting postgres" | ||
| exec docker-entrypoint.sh "$@" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,7 @@ | ||
| FROM postgres:18@sha256:06cad38a5d9f5d24b4d83d86def30795d5e4b757fedbf5281172b576dedcd941 | ||
|
|
||
| COPY ./docker-entrypoint-initdb.d/00_enable_ssl.sh /docker-entrypoint-initdb.d/ | ||
|
|
||
| COPY entrypoint.sh /usr/local/bin/ | ||
| ENTRYPOINT ["entrypoint.sh"] | ||
| CMD ["postgres"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| # Copyright (c) 2026 Alexander Todorov <atodorov@otb.bg> | ||
| # | ||
| # Licensed under GNU Affero General Public License v3 or later (AGPLv3+) | ||
| # https://www.gnu.org/licenses/agpl-3.0.html | ||
|
|
||
| echo "INFO: check if replication is configured" | ||
| if [ ! -s "$PGDATA/PG_VERSION" ] && [ -n "$POSTGRES_REPLICATION_USER" ]; then | ||
| mkdir -p "$PGDATA" | ||
| chmod 00700 "$PGDATA" || : | ||
|
|
||
| if [ -z "$POSTGRES_REPLICATION_PASSWORD" ]; then | ||
| echo "ERROR: POSTGRES_REPLICATION_PASSWORD is undefined" | ||
| exit 1 | ||
| fi | ||
|
|
||
| if [ -z "$POSTGRES_PRIMARY_HOST" ]; then | ||
| echo "ERROR: POSTGRES_PRIMARY_HOST is undefined" | ||
| exit 2 | ||
| fi | ||
|
|
||
| echo "INFO: starting initial wal sync" | ||
| pg_basebackup \ | ||
| --dbname "postgres://$POSTGRES_REPLICATION_USER:$POSTGRES_REPLICATION_PASSWORD@$POSTGRES_PRIMARY_HOST/postgres?sslmode=require" \ | ||
| --pgdata "$PGDATA" \ | ||
| --progress --verbose --write-recovery-conf --wal-method stream \ | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same slot-name collision concern as in 17/entrypoint.sh — slot is named after the replication user, so multiple replicas sharing the user will conflict. |
||
| --create-slot --slot "$POSTGRES_REPLICATION_USER" | ||
|
|
||
| echo "INFO: completed initial wal sync" | ||
| fi | ||
|
|
||
| echo "INFO: starting postgres" | ||
| exec docker-entrypoint.sh "$@" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ services: | |
| restart: always | ||
| volumes: | ||
| - db17_data:/var/lib/postgresql | ||
| - ./initdb.d/01_replication_users.sh:/docker-entrypoint-initdb.d/01_replication_users.sh:Z | ||
| environment: | ||
| POSTGRES_DB: kiwitcms | ||
| POSTGRES_USER: kiwitcms | ||
|
|
@@ -73,6 +74,7 @@ services: | |
| dockerfile: Dockerfile | ||
| volumes: | ||
| - db18_data:/var/lib/postgresql | ||
| - ./initdb.d/01_replication_users.sh:/docker-entrypoint-initdb.d/01_replication_users.sh:Z | ||
|
|
||
| web: | ||
| container_name: web | ||
|
|
@@ -99,3 +101,8 @@ services: | |
| volumes: | ||
| db17_data: | ||
| db18_data: | ||
|
|
||
|
|
||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pinning the network name to |
||
| networks: | ||
| default: | ||
| name: postgres_default | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| #!/bin/bash | ||
|
|
||
| # Copyright (c) 2026 Alexander Todorov <atodorov@otb.bg> | ||
| # | ||
| # Licensed under GNU Affero General Public License v3 or later (AGPLv3+) | ||
| # https://www.gnu.org/licenses/agpl-3.0.html | ||
|
|
||
| set -eu | ||
|
|
||
| replication_user() { | ||
| local username=$1 | ||
| local password=$2 | ||
|
|
||
| psql --set ON_ERROR_STOP=1 \ | ||
| --set=username="$username" \ | ||
| --set=password="$password" \ | ||
| --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL | ||
| CREATE USER :"username" WITH ENCRYPTED PASSWORD :'password' REPLICATION; | ||
| EOSQL | ||
| } | ||
|
|
||
| replication_user "rpl_usr_17" "replicate-me" | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both replication users are created with the same hard-coded password |
||
| replication_user "rpl_usr_18" "replicate-me" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -37,6 +37,16 @@ rlJournalStart | |
| rlAssertGrep "pg_hba.conf rejects connection .* no encryption" "$rlRun_LOG" | ||
| rlPhaseEnd | ||
|
|
||
| rlPhaseStartTest "Start replication containers" | ||
| rlRun -t -c "docker run -d --name=replica_17 --network=postgres_default -e POSTGRES_REPLICATION_USER=rpl_usr_17 -e POSTGRES_REPLICATION_PASSWORD=replicate-me -e POSTGRES_PRIMARY_HOST=postgres_17 postgres-postgres_17:latest" | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Two fixed |
||
| sleep 120 | ||
| rlRun -t -c "docker logs replica_17" | ||
|
|
||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The replicas are started with |
||
| rlRun -t -c "docker run -d --name=replica_18 --network=postgres_default -e POSTGRES_REPLICATION_USER=rpl_usr_18 -e POSTGRES_REPLICATION_PASSWORD=replicate-me -e POSTGRES_PRIMARY_HOST=postgres_18 postgres-postgres_18:latest" | ||
| sleep 120 | ||
| rlRun -t -c "docker logs replica_18" | ||
| rlPhaseEnd | ||
|
|
||
| rlPhaseStartTest "Container restart" | ||
| rlRun -t -c "docker compose restart" | ||
| assert_up_and_running | ||
|
|
@@ -56,7 +66,21 @@ rlJournalStart | |
| assert_up_and_running | ||
| rlPhaseEnd | ||
|
|
||
| rlPhaseStartTest "Check content in replicated databases" | ||
| REPLICA_17_ADDRESS=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' replica_17) | ||
| rlRun -t -c "psql --dbname 'postgres://kiwitcms:kiwitcms@$REPLICA_17_ADDRESS/kiwitcms?sslmode=require' -c 'SELECT * FROM management_priority;' | grep '5 rows'" | ||
|
|
||
| REPLICA_18_ADDRESS=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' replica_18) | ||
| rlRun -t -c "psql --dbname 'postgres://kiwitcms:kiwitcms@$REPLICA_18_ADDRESS/kiwitcms?sslmode=require' -c 'SELECT * FROM management_priority;' | grep '5 rows'" | ||
| rlPhaseEnd | ||
|
|
||
| rlPhaseStartCleanup | ||
| rlRun -t -c "docker kill replica_17" | ||
| rlRun -t -c "docker rm replica_17" | ||
|
|
||
| rlRun -t -c "docker kill replica_18" | ||
| rlRun -t -c "docker rm replica_18" | ||
|
|
||
| rlRun -t -c "docker compose down" | ||
| if [ -n "$ImageOS" ]; then | ||
| rlRun -t -c "docker volume rm postgres_db17_data" | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.