Skip to content

Repository files navigation

gh-action-ecr-sync

GitHub Action to sync Docker Hub repositories into a private AWS ECR registry with multi-arch support.

Problem

Docker Hub enforces rate limits that can disrupt CI/CD pipelines and infrastructure that pulls images directly. AWS ECR provides a private registry without pull limits and free intra-region traffic.

This action syncs Docker Hub repos into ECR on a schedule, keeping your infrastructure independent of Docker Hub availability and rate limits.

Features

  • Multi-arch support — syncs complete manifest lists (arm64, amd64, armv7, etc.) via skopeo copy --all
  • Incremental sync — compares manifest digests and only syncs changed or new tags
  • No skopeo required — automatically uses a Docker container if skopeo is not installed on the runner
  • Tag limit — configurable limit per repo to control how many tags are synced

Prerequisites

  • AWS ECR repositories must already exist for the images you want to sync
  • IAM permissions: ecr:ListImages, ecr:BatchGetImage, ecr:PutImage, ecr:InitiateLayerUpload, ecr:UploadLayerPart, ecr:CompleteLayerUpload, ecr:BatchCheckLayerAvailability
  • Docker must be available on the runner (for skopeo container fallback)

Usage

name: ECR Sync
on:
  schedule:
    - cron: '15 1 * * *'
  workflow_dispatch:

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Dockerhub login
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-region: eu-central-1
      - name: Login to Amazon ECR
        id: ecr-login
        uses: aws-actions/amazon-ecr-login@v2
      - name: Sync repos
        uses: visable-dev/gh-action-ecr-sync@v2
        with:
          ecr_registry: ${{ steps.ecr-login.outputs.registry }}
          repo_file: ./repos.json
          tag_limit: 25

Repo file format

A JSON file that maps Docker Hub repo names to ECR repo names:

{
  "<dockerhub-repo>": "<ecr-repo>"
}

Example

Given ecr_registry as 123456789100.dkr.ecr.eu-central-1.amazonaws.com and:

{
  "oryd/kratos": "oryd/kratos",
  "nginx": "foobar/nginx"
}

The action syncs:

  • docker.io/oryd/kratos123456789100.dkr.ecr.eu-central-1.amazonaws.com/oryd/kratos
  • docker.io/library/nginx123456789100.dkr.ecr.eu-central-1.amazonaws.com/foobar/nginx

All architectures (amd64, arm64, etc.) are synced as a manifest list.

Inputs

Input Required Description
ecr_registry Yes ECR registry URL, e.g. 123456789100.dkr.ecr.eu-central-1.amazonaws.com
repo_file Yes Path to JSON file with repo mappings (see above)
tag_limit No Max number of tags per repo to sync, ordered by last updated. Default: unlimited

Migration from v1

v2 replaces docker pull/tag/push with skopeo copy --all. Key differences:

  • Images are now pushed as manifest lists (Image Index) instead of single-arch manifests
  • Existing single-arch images in ECR are preserved but will be replaced with manifest lists on next sync
  • Docker Hub login is now required (was optional in v1) to avoid rate limits with skopeo
  • No sudo or package manager access required — skopeo runs via Docker container if not natively available

About

Github Action which syncs docker images from dockerhub into private AWS ECR registry.

Topics

Resources

Stars

1 star

Watchers

13 watching

Forks

Releases

Packages

Used by

Contributors

Languages