diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2d883e3 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.git +.github +graphify-out +*.md +LICENSE +install.sh +completions diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..8ee75d8 --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,63 @@ +name: Docker + +on: + push: + branches: [main] + tags: ["v*"] + pull_request: + branches: [main] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + smoke: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build image + run: docker build -t pgsync:ci . + + - name: Version smoke test + run: docker run --rm pgsync:ci --version + + - name: Compose sync smoke test + run: PGSYNC_IMAGE=pgsync:ci docker compose run --rm pgsync + + publish: + runs-on: ubuntu-latest + needs: smoke + if: github.event_name != 'pull_request' + permissions: + contents: read + packages: write + + steps: + - uses: actions/checkout@v4 + + - uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - uses: docker/metadata-action@v5 + id: meta + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha,prefix= + type=raw,value=latest,enable={{is_default_branch}} + + - uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3795073 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +graphify-out/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4423336 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM postgres:16-bookworm + +LABEL org.opencontainers.image.source="https://github.com/mamahoos/pgsync" +LABEL org.opencontainers.image.description="PostgreSQL logical sync (pg_dump | psql)" + +COPY pgsync.sh /usr/local/bin/pgsync +RUN chmod 755 /usr/local/bin/pgsync + +ENTRYPOINT ["pgsync"] +CMD ["--help"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..6853442 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,54 @@ +# Local demo / CI smoke test: two Postgres instances + one-shot sync. +# +# Smoke test: +# docker compose run --rm pgsync +# +# Custom URIs (external clusters): +# docker compose run --rm pgsync \ +# -s 'postgresql://user:pass@host:5432/src' \ +# -t 'postgresql://user:pass@host:5432/dst' +# +# Pull from GHCR instead of building locally: +# PGSYNC_IMAGE=ghcr.io/mamahoos/pgsync:latest docker compose run --rm pgsync + +services: + source: + image: postgres:16-alpine + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: app + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres -d app"] + interval: 2s + timeout: 5s + retries: 15 + start_period: 5s + + target: + image: postgres:16-alpine + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: app + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres -d app"] + interval: 2s + timeout: 5s + retries: 15 + start_period: 5s + + pgsync: + image: ${PGSYNC_IMAGE:-ghcr.io/mamahoos/pgsync:latest} + build: . + depends_on: + source: + condition: service_healthy + target: + condition: service_healthy + command: + - -s + - postgresql://postgres:postgres@source:5432/app + - -t + - postgresql://postgres:postgres@target:5432/app + - -v