{"id":16161459,"url":"https://github.com/gamemann/postgresql-docker-image-with-backups","last_synced_at":"2025-03-18T22:30:45.896Z","repository":{"id":224172421,"uuid":"762622529","full_name":"gamemann/postgresql-docker-image-with-backups","owner":"gamemann","description":"A custom Docker image based off of PostgreSQL's Docker image that implements Cron jobs and a backup Bash script that uploads a database dump to Backblaze B2.","archived":false,"fork":false,"pushed_at":"2024-02-25T22:45:34.000Z","size":30,"stargazers_count":13,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-28T12:30:19.973Z","etag":null,"topics":["b2","backblaze","backup","backups","bash","docker","docker-compose","dockerfile","duplicity","logging","postgres","postgresql","script","storage","supervisor","supervisord"],"latest_commit_sha":null,"homepage":"https://deaconn.net/","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/gamemann.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}},"created_at":"2024-02-24T08:11:42.000Z","updated_at":"2025-02-16T12:55:39.000Z","dependencies_parsed_at":"2024-02-24T09:26:50.809Z","dependency_job_id":"6b74e749-6b08-466b-ba60-4147b605ce2f","html_url":"https://github.com/gamemann/postgresql-docker-image-with-backups","commit_stats":null,"previous_names":["gamemann/postgresql-docker-image-with-backups"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamemann%2Fpostgresql-docker-image-with-backups","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamemann%2Fpostgresql-docker-image-with-backups/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamemann%2Fpostgresql-docker-image-with-backups/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gamemann%2Fpostgresql-docker-image-with-backups/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gamemann","download_url":"https://codeload.github.com/gamemann/postgresql-docker-image-with-backups/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243950878,"owners_count":20373664,"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","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":["b2","backblaze","backup","backups","bash","docker","docker-compose","dockerfile","duplicity","logging","postgres","postgresql","script","storage","supervisor","supervisord"],"created_at":"2024-10-10T02:25:19.096Z","updated_at":"2025-03-18T22:30:45.677Z","avatar_url":"https://github.com/gamemann.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"This is a custom Docker image based off of the PostgreSQL Docker image [here](https://github.com/docker-library/postgres). This image uses [Supervisor](http://supervisord.org/) to start both Cron and the PostgreSQL server.\n\nAdditionally, a cron job is installed inside of the image ([`image/conf/cron.conf`](./image/conf/cron.conf)) that executes a backup script written in Bash ([`image/scripts/backup.sh`](./image/scripts/backup.sh)). The backup script dumps the database `$POSTGRES_DB` with the user `$POSTGRES_USER` to `/tmp/dbname.pgsql`. Afterwards, it uploads the database dump to a [Backblaze B2](https://www.backblaze.com/cloud-storage) bucket using [Duplicity](https://duplicity.us/) and deletes the local database dump.\n\nThe image itself is stored inside of the [`image/`](./image) directory. There is also a Docker Compose application you can refer to/use inside of the [`app/`](./app) directory which shows how to utilize this image.\n\n## Installation\n### Image\nThe image is stored in the [`image/`](./image) directory. You can use the `build_image.sh` Bash script to build the Docker image with the name/tag `postgresbackups:latest`. The following arguments are supported.\n\n| Flag | Default | Description |\n| ---- | ------- | ----------- |\n| `--name=\u003cNAME\u003e` | `postgresbackups` | The name of the Docker image. |\n| `--tag=\u003cTAG\u003e` | `latest` | The tag to set the Docker image to. |\n| `--path=\u003cPATH\u003e` | `image/` | Builds the Docker image inside of `\u003cPATH\u003e`. |\n| `--ptag=\u003cTAG\u003e` | `latest` | Builds Docker image based off of the PostgreSQL image with the tag `\u003cTAG\u003e`. |\n| `--no-cache` | - | Builds the Docker image with no cache. |\n| `--help` | - | Prints the help menu. |\n\nYou may also build the image manually using the following command as root (or using `sudo`).\n\n```bash\ndocker build -t postgresbackups:latest image\n```\n\n### Application\nThe application ([`app/`](./app)) uses Docker Compose with the latest backup image built above. Before using this, please make sure you have created a `db-data/` directory where the `docker-compose.yml` file resides. This directory is mounted to `/var/lib/postgresql/data` inside of the Docker container and stores database-specific files.\n\nYou may also need to change the owner of the `db-data/` directory to the system user (`999`) via the `chown -R 999 db-data` command since the `postgres` user inside of the Docker container has a GUID of `999` by default (at least in my cases while testing).\n\nWith that said, make sure to copy or rename [`app/.env.example`](./app/.env.example) to `app/.env`!\n\nFeel free to implement the application into your existing Docker Compose projects!\n\nRead [configuration](#configuration) for more information on setting up the project.\n\n## Configuration\nAll configuration is done using environmental variables inside of the Docker container. In the Docker Compose application inside this repository ([`app/`](./app)), we store the environmental variables inside of the [`app/.env`](./app/.env.example) file. By default, the file is called `.env.example`. Therefore, make sure to rename or copy it to `.env`.\n\nHere are a list of environmental variables you should pay attention to and configure.\n\n| Name | Default | Description |\n| ---- | ------- | ----------- |\n| POSTGRES_USER | `testuser` | The PostgreSQL username (inherited from PostgreSQL image). |\n| POSTGRES_PASSWORD | `testpass` | The PostgreSQL password (inherited from PostgreSQL image). |\n| POSTGRES_DB | `testdb` | The PostgreSQL database name (inherited from PostgreSQL image). |\n| BACKUP_VERBOSE | `1` | The backup script's verbose level. Log messages go up to verbose level `4` currently. |\n| BACKUP_LOG_DIR | `/var/log/backups` | The backup script's log directory inside of the Docker container. Leave blank to disable logging to files. |\n| BACKUP_B2_APP_KEY | `null` | The Backblaze B2 application master key. |\n| BACKUP_B2_ID | `null` | The Backblaze B2 application master ID. |\n| BACKUP_B2_BUCKET | `mybucket` | The Backblaze B2 bucket name to store backups in. |\n| BACKUP_B2_DIR | `testdb` | The directory to save the backup to inside of the B2 bucket. Use an empty string if you want to save it to the root of the bucket. |\n| BACKUP_DUP_FORCE_INC | `0` | Forces Duplicity to perform an incremental backup. |\n| BACKUP_DUP_FORCE_FULL | `0` | Forces Duplicity to perform a full backup. |\n| BACKUP_DUP_PASS | `12345` | This is the GnuPG passphrase which is required for restoring the backup. Change this! |\n\nBy default, the cron job is ran every day at 12:00 midnight. However, you can easily change this by editing the [`image/conf/cron.conf`](./image/conf/cron.conf) file and rebuilding the image. You can use a cron generator tool such as [this](https://crontab.cronhub.io/) for assistance!\n\nAdditionally, you may edit the application's PostgreSQL server's configuration by editing the [`app/conf/postgresql.conf`](./app/conf/postgresql.conf) file and rebuilding the Docker container.\n\n## Application Logging\nThe [`app/logs/`](./app/logs) directory is mounted as a volume to `/var/log/backups` inside of the Docker container. Therefore, logs should persist in this directory between rebuilds and restarts of the Docker container assuming the `$BACKUP_LOG_DIR` environmental variable is set to `/var/log/backups`.\n\n## Duplicity\nThe Duplicity command/functionality used to upload the database dump to the Backblaze B2 bucket is fairly simple and shown below.\n\n```bash\nDUP_CMD=\"\"\n\nif [[ \"$BACKUP_DUP_FORCE_INC\" -ge 1 ]]; then\n    DUP_CMD=\"inc\"\nelif [[ \"BACKUP_DUP_FORCE_FULL\" -ge 1 ]]; then\n    DUP_CMD=\"full\"\nfi\n\nDIR=\n\nif [[ -n \"$BACKUP_B2_DIR\" ]]; then\n    DIR=\"/${BACKUP_B2_DIR}\"\nfi\n\nenv PASSPHRASE=\"$BACKUP_DUP_PASS\" duplicity $DUP_CMD \"$FULL_DUMP_PATH\" \"b2://${BACKUP_B2_ID}:${BACKUP_B2_APP_KEY}@${BACKUP_B2_BUCKET}${DIR}\"\n```\n\nIf you need any flags, etc. added to this command, you may edit the [`image/scripts/backup.sh`](./image/scripts/backup.sh) Bash script and rebuild the Docker container.\n\n## Executing Backup Script Manually\nYou can start a shell inside of the Docker container using the following command.\n\n```bash\ndocker exec -it \u003ccontainer ID or name\u003e bash\n```\n\nYou can retrieve the container ID or name via the `docker container ls` command after starting the container.\n\nAfterwards, you can execute the backup Bash script manually at `/opt/backup.sh` to test if things are working properly without needing to adjust/wait for the cron job.\n\nAdditionally, the environmental variables inside of the [`app/.env`](./app/.env.example) file should be set inside of this shell. You can confirm this by executing the `printenv` command.\n\n## Credits\n* [Christian Deacon](https://github.com/gamemann)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgamemann%2Fpostgresql-docker-image-with-backups","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgamemann%2Fpostgresql-docker-image-with-backups","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgamemann%2Fpostgresql-docker-image-with-backups/lists"}