diff --git a/.github/workflows/image-publish.yaml b/.github/workflows/image-publish.yaml new file mode 100644 index 0000000..c398fc8 --- /dev/null +++ b/.github/workflows/image-publish.yaml @@ -0,0 +1,57 @@ +name: Publish a container image + +on: + push: + release: + types: [published, edited] + +jobs: + build: + runs-on: ubuntu-24.04 + permissions: + packages: write + steps: + - uses: actions/checkout@v6 + - uses: docker/setup-qemu-action@v3 + - run: ./build/set_image_metadata + - uses: docker/setup-compose-action@v1 + - name: Build an image + id: build-image + uses: redhat-actions/buildah-build@v2 + with: + image: ${{ github.event.repository.name }}-dev + tags: ${{ env.TAGS }} + platforms: linux/amd64, linux/arm64/v8 + containerfiles: | + ./Containerfile + labels: ${{ env.ANNOTATIONS }} + + - name: Push the image to GHCR + id: push-to-ghcr + uses: redhat-actions/push-to-registry@v2 + with: + image: ${{ steps.build-image.outputs.image }} + tags: ${{ steps.build-image.outputs.tags }} + registry: ghcr.io/${{ github.repository_owner }} + username: ${{ github.actor }} + password: ${{ github.token }} + + + - name: Set the version tag (only if released) + id: retag-version + if: (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'edited')) + run: | + buildah tag \ + ${{ steps.build-image.outputs.image }}:${{ github.sha }} \ + ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:latest + buildah tag \ + ${{ steps.build-image.outputs.image }}:${{ github.sha }} \ + ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ github.event.release.tag_name }} + + - name: Push the release image to GHCR + if: (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'edited')) + uses: redhat-actions/push-to-registry@v2 + with: + tags: ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:latest ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ github.event.release.tag_name }} + username: ${{ github.actor }} + password: ${{ github.token }} diff --git a/Containerfile b/Containerfile new file mode 100644 index 0000000..07186a9 --- /dev/null +++ b/Containerfile @@ -0,0 +1,12 @@ +FROM postgres:18-alpine + +RUN apk --no-cache add \ + curl \ + bash \ + rclone + +COPY entrypoint.sh / +RUN chmod +x /entrypoint.sh + +WORKDIR /backup +ENTRYPOINT /entrypoint.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..4b79a85 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# pgdump-gcs + +Small docker container for creating a backup of a psql database and upload the dump to an external storage using rclone. + +## How to use +TO BE DONE ... + +## monitoring + +Simple curl pushing some basic parameter to a prometheus push gateway. + +### metrics +* timestamp +* duration +* size + +### labels +* job = pgdump-gcs +* source_type = postgresql +* source_name = `${DB_NAME}` diff --git a/build/set_image_metadata b/build/set_image_metadata new file mode 100755 index 0000000..f341f78 --- /dev/null +++ b/build/set_image_metadata @@ -0,0 +1,35 @@ +#! /usr/bin/env bash +# -------------------------------------------- +# -- Should be used in Github Actions +# -------------------------------------------- +# +# -------------------------------------------- +# -- To have a multi-line env var in github, +# -- we must define the EOF +# -------------------------------------------- +EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) +echo "ANNOTATIONS<<$EOF" >> "$GITHUB_ENV" + +ANNOTATIONS=$(cat << EOF +org.opencontainers.image.created=$(date +"%Y-%m-%d %T") +org.opencontainers.image.authors=$GITHUB_ACTOR +org.opencontainers.image.url=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID +org.opencontainers.image.documentation=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/blob/main/README.md +org.opencontainers.image.source=$GITHUB_SERVER_URL/$GITHUB_REPOSITORY +org.opencontainers.image.version=$GITHUB_SHA +org.opencontainers.image.revision=$GITHUB_SHA +org.opencontainers.image.vendor=$GITHUB_REPOSITORY_OWNER +org.opencontainers.image.license=GNU GENERAL PUBLIC LICENSE v3 +org.opencontainers.image.title=$GITHUB_REPOSITORY +org.opencontainers.image.description=Backup databases using pg_dump and upload backups using rclone +EOF +) + +echo "${ANNOTATIONS}" >> "${GITHUB_ENV}" +echo "$EOF" >> "$GITHUB_ENV" +# -------------------------------------------- +# -- Set the image tag by commit sha +# -------------------------------------------- +echo "TAGS=${GITHUB_SHA}" >> "${GITHUB_ENV}" + + diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..2b4b50b --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,48 @@ +#!/bin/bash +set -e + +echo "Prepare configuration for script" +TIMESTAMP=$(date +%F_%R) +START_TIMESTAMP=$(date +%s) +BACKUP_FILE=${DB_NAME}-${TIMESTAMP}.sql.gz +BACKUP_FILE_LATEST=${DB_NAME}-latest.sql.gz +DB_HOST=${DB_HOST:-localhost} +DB_PASSWORD=$(cat ${DB_PASSWORD_FILE}) +DB_USER=$(cat ${DB_USERNAME_FILE}) +PROM_NAMESPACE=${PROM_NAMESPACE:-dboperator} + +if [[ -z "${STORAGE_BUCKET}" ]]; then + echo "Variable STORAGE_BUCKET must be set" + exit 1 +fi + +# create login credential file +(umask 377 && echo *:5432:*:${DB_USER}:${DB_PASSWORD} >> ~/.pgpass) + +echo "Start create backup" +pg_dump -F c -Z 9 -h ${DB_HOST} -p 5432 -U ${DB_USER} ${DB_NAME} -f ${BACKUP_FILE} +BACKUP_SIZE=$(du ${BACKUP_FILE} | awk '{print $1}') +echo "End backup" + +## copy to destination +echo "Copy to gcs" +rclone copyto "./${BACKUP_FILE}" "storage://${STORAGE_BUCKET}/${DB_NAME}/${BACKUP_FILE}" +rclone copyto "./${BACKUP_FILE}" "storage://${STORAGE_BUCKET}/${DB_NAME}/${BACKUP_FILE_LATEST}" + +END_TIMESTAMP=$(date +%s) +BACKUP_DURATION=$((END_TIMESTAMP - START_TIMESTAMP)) +if [[ ! -z "$PROMETHEUS_PUSH_GATEWAY" ]]; +then +echo "sending monitoring metrics to ${PROMETHEUS_PUSH_GATEWAY}" +cat <