{"id":27455530,"url":"https://github.com/stephane-klein/pg_back-docker-sidecar","last_synced_at":"2025-10-11T00:15:43.657Z","repository":{"id":287529143,"uuid":"964696300","full_name":"stephane-klein/pg_back-docker-sidecar","owner":"stephane-klein","description":"pg_back (PostgreSQL backup) in a Docker Sidecar ","archived":false,"fork":false,"pushed_at":"2025-08-16T21:00:29.000Z","size":55,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-07T07:34:28.551Z","etag":null,"topics":["backup","docker","postgresql","sidecar-container"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stephane-klein.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-11T16:26:22.000Z","updated_at":"2025-08-16T14:32:34.000Z","dependencies_parsed_at":"2025-04-14T15:35:29.014Z","dependency_job_id":"075a2a9f-5311-4a1d-8e70-649dc582beb6","html_url":"https://github.com/stephane-klein/pg_back-docker-sidecar","commit_stats":null,"previous_names":["stephane-klein/poc-pg_back","stephane-klein/pg_back-docker-sidecar"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/stephane-klein/pg_back-docker-sidecar","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stephane-klein%2Fpg_back-docker-sidecar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stephane-klein%2Fpg_back-docker-sidecar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stephane-klein%2Fpg_back-docker-sidecar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stephane-klein%2Fpg_back-docker-sidecar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stephane-klein","download_url":"https://codeload.github.com/stephane-klein/pg_back-docker-sidecar/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stephane-klein%2Fpg_back-docker-sidecar/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279005657,"owners_count":26083941,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-10T02:00:06.843Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backup","docker","postgresql","sidecar-container"],"created_at":"2025-04-15T16:43:58.251Z","updated_at":"2025-10-11T00:15:43.649Z","avatar_url":"https://github.com/stephane-klein.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pg_back Docker Sidecar\n\nInitially, in this repository I wanted to test the implementation of [pg_back](https://github.com/orgrim/pg_back/) deployed in a Docker container as a \"sidecar\" to backup a PostgreSQL database deployed via Docker.\n\nAnd gradually, I changed the objective of this project. Now it contains\n\n- source code to build a Docker Sidecar image named [`stephaneklein/pg_back-docker-sidecar`](https://hub.docker.com/repository/docker/stephaneklein/pg_back-docker-sidecar/general)\n- a step-by-step tutorial that presents all aspects of using this container\n- a workspace that allows me to contribute to the upstream `pg_back` project: [`./src/`](./src/)\n\nFor more context, see the following note written in French: https://notes.sklein.xyz/Projet%2027/\n\n## How to use pg_back Docker Sidecar in production?\n\nHere's an example of a `docker-compose.yml` for using `pg_back-docker-sidecar` in production.\n\nFor more information about the role and usage of `pg_back-docker-sidecar` environment variables, you can consult the content of the [`pg_back.conf.tmpl`](https://github.com/stephane-klein/pg_back-docker-sidecar/blob/main/pg_back.conf.tmpl) file.\n\nYou can select the PostgreSQL version that will be used by *pg_back* by specifying the version number in the `POSTGRES_VERSION` environment variable, for example `POSTGRES_VERSION=17` (the `stephaneklein/pg_back-docker-sidecar` Docker image supports PostgreSQL versions `15`, `16`, and `17`).\n\n```\nservices:\n  postgres1:\n    image: postgres:17\n    restart: unless-stopped\n    ports:\n      - 5432\n    environment:\n      POSTGRES_DB: postgres\n      POSTGRES_USER: postgres\n      POSTGRES_PASSWORD: password\n    volumes:\n      - postgres1:/var/lib/postgresql/data/\n    healthcheck:\n      test: [\"CMD\", \"sh\", \"-c\", \"pg_isready -U $$POSTGRES_USER -h $$(hostname -i)\"]\n      interval: 10s\n      start_period: 30s\n\n  pg_back:\n    image: stephaneklein/pg_back-docker-sidecar\n    restart: no\n    environment:\n      POSTGRES_VERSION: 17\n      POSTGRES_HOST: postgres1\n      POSTGRES_PORT: 5432\n      POSTGRES_USER: postgres\n      POSTGRES_DB: postgres\n      POSTGRES_PASSWORD: password\n      \n      BACKUP_CRON: \"0 3 * * *\"\n      UPLOAD: \"s3\"\n      UPLOAD_PREFIX: \"foobar\"\n\n      S3_KEY_ID: admin\n      S3_SECRET: password\n      S3_ENDPOINT: \"....\"\n      S3_REGION: \"...\"\n      S3_BUCKET: \"pg-back\"\n      S3_FORCE_PATH: \"true\"\n      S3_TLS: \"false\"\n\n      PURGE_OLDER_THAN: \"60s\"\n      PURGE_REMOTE: \"true\"\n\n      ENCRYPT: \"true\"\n      AGE_CIPHER_PUBLIC_KEY: \"...\"\n      AGE_CIPHER_PRIVATE_KEY: \"...\"\n\n    depends_on:\n      postgres1:\n        condition: service_healthy\n      minio:\n        condition: service_healthy\n```\n\n## Step by step tutorial for using pg_back Docker Sidecar locally\n\n### Prerequisites\n\n- [mise](https://mise.jdx.dev/)\n- [Docker Engine](https://docs.docker.com/engine/) (tested with `24.0.6`)\n\n### Environment preparation\n\nIf you don't use [Mise](https://mise.jdx.dev/) or [direnv](https://direnv.net/), you need to execute the following command before running `docker compose`:\n\n```\n$ source .envrc\n```\n\n```sh\n$ mise install\n$ docker compose build\n```\n\n### Start or restart the playground test scenario\n\nI start by resetting the environment:\n\n```sh\n$ docker compose down -v\n[+] Running 9/9\n ✔ Container poc_pg_back_66ce9ade1421-pg_back2-1   Removed                 10.2s\n ✔ Container poc_pg_back_66ce9ade1421-postgres2-1  Removed                  0.2s\n ✔ Container poc_pg_back_66ce9ade1421-pg_back1-1   Removed                 10.2s\n ✔ Container poc_pg_back_66ce9ade1421-minio-1      Removed                  0.4s\n ✔ Container poc_pg_back_66ce9ade1421-postgres1-1  Removed                  0.3s\n ✔ Volume poc_pg_back_66ce9ade1421_postgres2       Removed                  0.0s\n ✔ Volume poc_pg_back_66ce9ade1421_minio           Removed                  0.1s\n ✔ Volume poc_pg_back_66ce9ade1421_postgres1       Removed                  0.1s\n ! Network poc_pg_back_66ce9ade1421_default        Resource is still in use 0.0s\n```\n\nI start the services:\n\n- `postgres1`, which is the PostgreSQL instance I want to backup\n- `minio` which serves as a local Object Storage\n- `pg_back` a \"Sidecar\" Docker container that executes the [`pg_back`](https://github.com/orgrim/pg_back/) commands and runs them daily with [supercronic](https://github.com/aptible/supercronic)\n\n```sh\n$ docker compose up -d postgres1 minio pg_back1 --wait\nWARN[0000] Found orphan containers ([poc_pg_back_66ce9ade1421-pg_back-1]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.\n[+] Running 5/5\n ✔ Volume \"poc_pg_back_66ce9ade1421_minio\"         Created                 0.0s\n ✔ Volume \"poc_pg_back_66ce9ade1421_postgres1\"     Created                 0.0s\n ✔ Container poc_pg_back_66ce9ade1421-minio-1      Healthy                 6.6s\n ✔ Container poc_pg_back_66ce9ade1421-postgres1-1  Healthy                 6.6s\n ✔ Container poc_pg_back_66ce9ade1421-pg_back1-1   Healthy                 6.4s\n```\n\nI prepare a Bucket in Minio named `pg-back`:\n\n```sh\n$ ./scripts/create-minio-bucket.sh\nAdded `myminio` successfully.\nBucket created successfully `myminio/pg-back`.\n```\n\nI create a data model and inject dummy data in the `postgres1` instance:\n\n```sh\n$ ./scripts/seed.sh\nNOTICE:  table \"dummy\" does not exist, skipping\nNOTICE:  function public.insert_dummy_records() does not exist, skipping\n$ ./scripts/generate_dummy_rows_in_postgres1.sh 1000\n```\n\nNow, I will execute a dump with `pg_back`:\n\n```sh\n$ ./scripts/execute-pg_back1-dump.sh\n2025/04/14 14:58:08 INFO: dumping globals\n2025/04/14 14:58:08 INFO: dumping instance configuration\n2025/04/14 14:58:08 INFO: encrypting /var/backups/postgresql/pg_globals_2025-04-14T14:58:08Z.sql\n2025/04/14 14:58:08 INFO: uploading /var/backups/postgresql/pg_globals_2025-04-14T14:58:08Z.sql.age to S3 bucket pg-back\n2025/04/14 14:58:08 INFO: encrypting /var/backups/postgresql/pg_settings_2025-04-14T14:58:08Z.out\n2025/04/14 14:58:08 INFO: encrypting /var/backups/postgresql/hba_file_2025-04-14T14:58:08Z.out\n2025/04/14 14:58:08 INFO: uploading /var/backups/postgresql/pg_settings_2025-04-14T14:58:08Z.out.age to S3 bucket pg-back\n2025/04/14 14:58:08 INFO: dumping database postgres\n2025/04/14 14:58:08 INFO: uploading /var/backups/postgresql/hba_file_2025-04-14T14:58:08Z.out.age to S3 bucket pg-back\n2025/04/14 14:58:08 INFO: encrypting /var/backups/postgresql/ident_file_2025-04-14T14:58:08Z.out\n2025/04/14 14:58:08 INFO: uploading /var/backups/postgresql/ident_file_2025-04-14T14:58:08Z.out.age to S3 bucket pg-back\n2025/04/14 14:58:08 INFO: encrypting /var/backups/postgresql/postgres_2025-04-14T14:58:08Z.dump\n2025/04/14 14:58:08 INFO: dump of postgres to /var/backups/postgresql/postgres_2025-04-14T14:58:08Z.dump done\n2025/04/14 14:58:08 INFO: uploading /var/backups/postgresql/postgres_2025-04-14T14:58:08Z.dump.age to S3 bucket pg-back\n2025/04/14 14:58:08 INFO: waiting for postprocessing to complete\n2025/04/14 14:58:08 INFO: purging old dumps\n```\n\nI wait a few seconds (30s) before injecting more data into `postgres1` and performing a new dump:\n\n```sh\n$ ./scripts/generate_dummy_rows_in_postgres1.sh 1000\n$ ./scripts/execute-pg_back1-dump.sh\n2025/04/14 14:58:39 INFO: dumping globals\n2025/04/14 14:58:39 INFO: dumping instance configuration\n2025/04/14 14:58:39 INFO: encrypting /var/backups/postgresql/pg_globals_2025-04-14T14:58:39Z.sql\n2025/04/14 14:58:39 INFO: uploading /var/backups/postgresql/pg_globals_2025-04-14T14:58:39Z.sql.age to S3 bucket pg-back\n2025/04/14 14:58:39 INFO: encrypting /var/backups/postgresql/pg_settings_2025-04-14T14:58:39Z.out\n2025/04/14 14:58:39 INFO: encrypting /var/backups/postgresql/hba_file_2025-04-14T14:58:39Z.out\n2025/04/14 14:58:39 INFO: uploading /var/backups/postgresql/pg_settings_2025-04-14T14:58:39Z.out.age to S3 bucket pg-back\n2025/04/14 14:58:39 INFO: dumping database postgres\n2025/04/14 14:58:39 INFO: encrypting /var/backups/postgresql/ident_file_2025-04-14T14:58:39Z.out\n2025/04/14 14:58:39 INFO: uploading /var/backups/postgresql/hba_file_2025-04-14T14:58:39Z.out.age to S3 bucket pg-back\n2025/04/14 14:58:39 INFO: uploading /var/backups/postgresql/ident_file_2025-04-14T14:58:39Z.out.age to S3 bucket pg-back\n2025/04/14 14:58:39 INFO: dump of postgres to /var/backups/postgresql/postgres_2025-04-14T14:58:39Z.dump done\n2025/04/14 14:58:39 INFO: encrypting /var/backups/postgresql/postgres_2025-04-14T14:58:39Z.dump\n2025/04/14 14:58:39 INFO: uploading /var/backups/postgresql/postgres_2025-04-14T14:58:39Z.dump.age to S3 bucket pg-back\n2025/04/14 14:58:39 INFO: waiting for postprocessing to complete\n2025/04/14 14:58:39 INFO: purging old dumps\n```\n\nHere is the list of files uploaded to Minio Object Storage:\n\n```sh\n$ ./scripts/execute-pg_back1-list-remote.sh\nfoobar/hba_file_2025-04-14T14:58:08Z.out.age\nfoobar/hba_file_2025-04-14T14:58:39Z.out.age\nfoobar/ident_file_2025-04-14T14:58:08Z.out.age\nfoobar/ident_file_2025-04-14T14:58:39Z.out.age\nfoobar/pg_globals_2025-04-14T14:58:08Z.sql.age\nfoobar/pg_globals_2025-04-14T14:58:39Z.sql.age\nfoobar/pg_settings_2025-04-14T14:58:08Z.out.age\nfoobar/pg_settings_2025-04-14T14:58:39Z.out.age\nfoobar/postgres_2025-04-14T14:58:08Z.dump.age\nfoobar/postgres_2025-04-14T14:58:39Z.dump.age\n```\n\nI observe something I don't like. Each backup consists of 5 files. These files are not grouped in a folder.\nI find this makes reading the list of backups difficult.\n\nI also observe that the `ENCRYPT: \"true\"` parameter has been taken into account, the archive files appear to be encrypted with Age.\n\nWith the patch \"[Add the --delete-local-file-after-upload to delete local file after upload](https://github.com/orgrim/pg_back/pull/143)\", after uploading to Object Storage, I can verify that the archive files are not present in the container filesystem:\n\n```sh\n$ docker compose exec pg_back1 ls /var/backups/postgresql/ -1\n```\n\nI now wait 45s before injecting data and performing a new dump.\nThis 45s waiting period allows me to observe if the `PURGE_OLDER_THAN: \"60s\"` parameter is\ncorrectly taken into account by `pg_back`.\n\n```sh\n$ ./scripts/generate_dummy_rows_in_postgres1.sh 1000\n$ ./scripts/execute-pg_back1-dump.sh\n2025/04/14 14:59:24 INFO: dumping globals\n2025/04/14 14:59:24 INFO: dumping instance configuration\n2025/04/14 14:59:24 INFO: encrypting /var/backups/postgresql/pg_globals_2025-04-14T14:59:24Z.sql\n2025/04/14 14:59:24 INFO: uploading /var/backups/postgresql/pg_globals_2025-04-14T14:59:24Z.sql.age to S3 bucket pg-back\n2025/04/14 14:59:24 INFO: encrypting /var/backups/postgresql/pg_settings_2025-04-14T14:59:24Z.out\n2025/04/14 14:59:24 INFO: encrypting /var/backups/postgresql/hba_file_2025-04-14T14:59:24Z.out\n2025/04/14 14:59:24 INFO: uploading /var/backups/postgresql/pg_settings_2025-04-14T14:59:24Z.out.age to S3 bucket pg-back\n2025/04/14 14:59:24 INFO: dumping database postgres\n2025/04/14 14:59:24 INFO: encrypting /var/backups/postgresql/ident_file_2025-04-14T14:59:24Z.out\n2025/04/14 14:59:24 INFO: uploading /var/backups/postgresql/hba_file_2025-04-14T14:59:24Z.out.age to S3 bucket pg-back\n2025/04/14 14:59:24 INFO: uploading /var/backups/postgresql/ident_file_2025-04-14T14:59:24Z.out.age to S3 bucket pg-back\n2025/04/14 14:59:25 INFO: dump of postgres to /var/backups/postgresql/postgres_2025-04-14T14:59:24Z.dump done\n2025/04/14 14:59:25 INFO: encrypting /var/backups/postgresql/postgres_2025-04-14T14:59:24Z.dump\n2025/04/14 14:59:25 INFO: uploading /var/backups/postgresql/postgres_2025-04-14T14:59:24Z.dump.age to S3 bucket pg-back\n2025/04/14 14:59:25 INFO: waiting for postprocessing to complete\n2025/04/14 14:59:25 INFO: purging old dumps\n2025/04/14 14:59:25 INFO: removing remote foobar/postgres_2025-04-14T14:58:08Z.dump.age\n2025/04/14 14:59:25 INFO: removing remote foobar/pg_globals_2025-04-14T14:58:08Z.sql.age\n2025/04/14 14:59:25 INFO: removing remote foobar/pg_settings_2025-04-14T14:58:08Z.out.age\n2025/04/14 14:59:25 INFO: removing remote foobar/hba_file_2025-04-14T14:58:08Z.out.age\n2025/04/14 14:59:25 INFO: removing remote foobar/ident_file_2025-04-14T14:58:08Z.out.age\n```\n\nI check that the first archive has been deleted:\n\n```sh\n$ ./scripts/execute-pg_back1-list-remote.sh\nfoobar/hba_file_2025-04-14T14:58:39Z.out.age\nfoobar/hba_file_2025-04-14T14:59:24Z.out.age\nfoobar/ident_file_2025-04-14T14:58:39Z.out.age\nfoobar/ident_file_2025-04-14T14:59:24Z.out.age\nfoobar/pg_globals_2025-04-14T14:58:39Z.sql.age\nfoobar/pg_globals_2025-04-14T14:59:24Z.sql.age\nfoobar/pg_settings_2025-04-14T14:58:39Z.out.age\nfoobar/pg_settings_2025-04-14T14:59:24Z.out.age\nfoobar/postgres_2025-04-14T14:58:39Z.dump.age\nfoobar/postgres_2025-04-14T14:59:24Z.dump.age\n```\n\nThis is how to download the latest archive locally:\n\n```sh\n$ ./scripts/download-dump.sh 2025-04-14T14:59:24\ndownload: s3://pg-back/foobar/pg_globals_2025-04-14T14:59:24Z.sql.age to tmp-downloads-dump/pg_globals_2025-04-14T14:59:24Z.sql.age\ndownload: s3://pg-back/foobar/hba_file_2025-04-14T14:59:24Z.out.age to tmp-downloads-dump/hba_file_2025-04-14T14:59:24Z.out.age\ndownload: s3://pg-back/foobar/postgres_2025-04-14T14:59:24Z.dump.age to tmp-downloads-dump/postgres_2025-04-14T14:59:24Z.dump.age\ndownload: s3://pg-back/foobar/pg_settings_2025-04-14T14:59:24Z.out.age to tmp-downloads-dump/pg_settings_2025-04-14T14:59:24Z.out.age\ndownload: s3://pg-back/foobar/ident_file_2025-04-14T14:59:24Z.out.age to tmp-downloads-dump/ident_file_2025-04-14T14:59:24Z.out.age\n```\n\nLes archives ont été download dans `./tmp-downloads-dump/`:\n\n```sh\n$ ls -lha ./tmp-downloads-dump/\ntotal 40K\ndrwxr-xr-x 1 stephane stephane  424 14 avril 16:59 .\ndrwxr-xr-x 1 stephane stephane  258 14 avril 16:52 ..\n-rw-r--r-- 1 stephane stephane   13 13 avril 10:42 .gitignore\n-rw-r--r-- 1 stephane stephane 5,9K 14 avril 16:59 hba_file_2025-04-14T14:59:24Z.out.age\n-rw-r--r-- 1 stephane stephane 2,9K 14 avril 16:59 ident_file_2025-04-14T14:59:24Z.out.age\n-rw-r--r-- 1 stephane stephane  719 14 avril 16:59 pg_globals_2025-04-14T14:59:24Z.sql.age\n-rw-r--r-- 1 stephane stephane  574 14 avril 16:59 pg_settings_2025-04-14T14:59:24Z.out.age\n-rw-r--r-- 1 stephane stephane 8,6K 14 avril 16:59 postgres_2025-04-14T14:59:24Z.dump.age\n-rw-r--r-- 1 stephane stephane   46 12 avril 17:48 README.md\n```\n\nDecrypting `*.age` archives with Age:\n\n```sh\n$ ./scripts/age-decrypt-downloads-dump.sh\n```\n\nI start the `postgres2` where I want to restore the backups:\n\n```sh\n$ docker compose up -d postgres2 --wait\nWARN[0000] Found orphan containers ([poc_pg_back_66ce9ade1421-pg_back-1]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.\n[+] Running 2/2\n ✔ Volume \"poc_pg_back_66ce9ade1421_postgres2\"     Created      0.0s\n ✔ Container poc_pg_back_66ce9ade1421-postgres2-1  Healthy      5.9s\n```\nImport `2025-04-14T14:59:24` local archive to `postgres2`:\n```sh\n$ ./scripts/postgres2-import-local-dump.sh 2025-04-14T14:59:24\n[+] Copying 1/1\n ✔ poc_pg_back_66ce9ade1421-postgres2-1 copy ./tmp-downloads-dump/pg_globals_2025-04-14T14:59:24Z.sql to poc_pg_back_66ce9ade1421-postgres2-1:/pg_globals.sql Copied                                                                                                                                                                                    0.0s\n[+] Copying 1/1\n ✔ poc_pg_back_66ce9ade1421-postgres2-1 copy ./tmp-downloads-dump/postgres_2025-04-14T14:59:24Z.dump to poc_pg_back_66ce9ade1421-postgres2-1:/postgres.dump Copied                                                                                                                                                                                      0.0s\n```\n\nNow I check that the `dummy` table and its data have been correctly restored in the `postgres2` instance:\n\n```sh\n$ echo \"select count(*) from dummy;\" | ./scripts/postgres2-sql.sh\n count\n-------\n  2100\n(1 row)\n\n```\n\nI will now use an alternative solution based on `pg_back` to restore the archives in `postgres2`.\n\nThen I start the `pg_back2` service. This service is configured with the `DISABLE_CRON: \"true\"` option, because I don't want\nto perform backups with this service.\n\n```sh\n$ docker compose up -d pg_back2 --wait\nWARN[0000] Found orphan containers ([poc_pg_back_66ce9ade1421-pg_back-1]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.\n[+] Running 3/3\n ✔ Container poc_pg_back_66ce9ade1421-postgres1-1  Healthy             1.4s\n ✔ Container poc_pg_back_66ce9ade1421-minio-1      Healthy             1.4s\n ✔ Container poc_pg_back_66ce9ade1421-pg_back2-1   Healthy             1.4s\n```\n\nBefore restoring data to `postgres2`, I start by emptying it by destroying and restarting the service:\n\n```sh\n$ docker compose down -v postgres2\n[+] Running 3/3\n ✔ Container poc_pg_back_66ce9ade1421-postgres2-1  Removed                   0.4s\n ✔ Volume poc_pg_back_66ce9ade1421_postgres2       Removed                   0.1s\n ! Network poc_pg_back_66ce9ade1421_default        Resource is still in use  0.0s\n$ docker compose up -d postgres2 --wait\nWARN[0000] Found orphan containers ([poc_pg_back_66ce9ade1421-pg_back-1]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.\n[+] Running 2/2\n ✔ Volume \"poc_pg_back_66ce9ade1421_postgres2\"     Created                   0.0s\n ✔ Container poc_pg_back_66ce9ade1421-postgres2-1  Healthy                   6.0s\n```\n\nI launch the restore of the latest archive to `postgres2`:\n\n```sh\n$ ./scritps/pg_back2-import-dump.sh 2025-04-14T14:59:24\n2025/04/14 14:59:41 INFO: downloading foobar/hba_file_2025-04-14T14:59:24Z.out.age from S3 bucket pg-back to /var/backups/postgresql/foobar/hba_file_2025-04-14T14:59:24Z.out.age\n2025/04/14 14:59:41 INFO: downloading foobar/ident_file_2025-04-14T14:59:24Z.out.age from S3 bucket pg-back to /var/backups/postgresql/foobar/ident_file_2025-04-14T14:59:24Z.out.age\n2025/04/14 14:59:41 INFO: downloading foobar/pg_globals_2025-04-14T14:59:24Z.sql.age from S3 bucket pg-back to /var/backups/postgresql/foobar/pg_globals_2025-04-14T14:59:24Z.sql.age\n2025/04/14 14:59:41 INFO: downloading foobar/pg_settings_2025-04-14T14:59:24Z.out.age from S3 bucket pg-back to /var/backups/postgresql/foobar/pg_settings_2025-04-14T14:59:24Z.out.age\n2025/04/14 14:59:41 INFO: downloading foobar/postgres_2025-04-14T14:59:24Z.dump.age from S3 bucket pg-back to /var/backups/postgresql/foobar/postgres_2025-04-14T14:59:24Z.dump.age\n2025/04/14 14:59:41 INFO: decrypting /var/backups/postgresql/foobar/hba_file_2025-04-14T14:59:24Z.out.age\n2025/04/14 14:59:41 INFO: decrypting /var/backups/postgresql/foobar/ident_file_2025-04-14T14:59:24Z.out.age\n2025/04/14 14:59:41 INFO: decrypting /var/backups/postgresql/foobar/pg_globals_2025-04-14T14:59:24Z.sql.age\n2025/04/14 14:59:41 INFO: decrypting /var/backups/postgresql/foobar/pg_settings_2025-04-14T14:59:24Z.out.age\n2025/04/14 14:59:41 INFO: decrypting /var/backups/postgresql/foobar/postgres_2025-04-14T14:59:24Z.dump.age\n```\n\nNow I check that the `dummy` table and its data have been correctly restored in the `postgres2` instance:\n\n```sh\n$ echo \"select count(*) from dummy;\" | ./scripts/postgres2-sql.sh\n count\n-------\n  2100\n(1 row)\n\n```\n\nI will now test if *cron* is working correctly.\n\nI check the number of backups already performed:\n\n```\n$ ./scripts/execute-pg_back1-list-remote.sh | grep \"pg_globals\"\nfoobar/pg_globals_2025-04-14T14:58:39Z.sql.age\nfoobar/pg_globals_2025-04-14T14:59:24Z.sql.age\n```\n\nI restart `pg_back1` by scheduling a backup in 2 minutes:\n\n```sh\n$ export BACKUP_CRON=$(date -u -d \"now + 2 minutes\" \"+%M %H * * *\")\n$ docker compose down pg_back1\n[+] Running 2/2\n ✔ Container poc_pg_back_66ce9ade1421-pg_back1-1  Removed                   10.4s\n ! Network poc_pg_back_66ce9ade1421_default       Resource is still in use  0.0s\n$ docker compose up -d pg_back1 --wait\nWARN[0000] Found orphan containers ([poc_pg_back_66ce9ade1421-pg_back-1]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.\n[+] Running 3/3\n ✔ Container poc_pg_back_66ce9ade1421-minio-1      Healthy                  1.3s\n ✔ Container poc_pg_back_66ce9ade1421-postgres1-1  Healthy                  1.3s\n ✔ Container poc_pg_back_66ce9ade1421-pg_back1-1   Healthy                  1.3s\n$ sleep 3m\n```\nI check that one more backup has been performed:\n\n```\n$ ./scripts/execute-pg_back1-list-remote.sh | grep \"pg_globals\"\nfoobar/pg_globals_2025-04-14T15:01:00Z.sql.age\n```\n\n### Hacking\n\nI had to make patches on the [pg_back](https://github.com/orgrim/pg_back/) project. To develop these patches, I used a workspace that I described in [`src/`](src/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstephane-klein%2Fpg_back-docker-sidecar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstephane-klein%2Fpg_back-docker-sidecar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstephane-klein%2Fpg_back-docker-sidecar/lists"}