How to Use GitHub Actions + image-syncer for Automated Image Sync from Docker Hub to Azure ACR
Редактировать страницуAutomating Image Sync from Docker Hub to Azure ACR
Заголовок раздела «Automating Image Sync from Docker Hub to Azure ACR»This article explains how to use GitHub Actions and the image-syncer tool to automate image synchronization from Docker Hub to Azure Container Registry, solving the problem of slow Docker Hub access in mainland China and some Azure regions, while improving image availability and deployment efficiency in Azure environments.
Background / Introduction
Заголовок раздела «Background / Introduction»The HagiCode project uses Docker images as its core runtime components, with the main images hosted on Docker Hub. As the project has evolved and Azure deployment needs have grown, we encountered the following pain points:
- Slow image pulls, because access to Docker Hub is limited in mainland China and some Azure regions
- Relying on a single image source creates a single point of failure risk
- Using Azure Container Registry in Azure environments provides better network performance and integration experience
To solve these problems, we need to establish an automated image synchronization mechanism that regularly syncs images from Docker Hub to Azure ACR, ensuring users get faster image pull speeds and higher availability in Azure environments.
About HagiCode
Заголовок раздела «About HagiCode»We are building HagiCode, an AI-driven coding assistant that makes development smarter, more convenient, and more enjoyable.
Smart: AI assistance throughout the entire process, from idea to code, boosting coding efficiency several times over. Convenient: Multi-threaded concurrent operations make full use of resources and keep the development workflow smooth. Fun: Gamification and an achievement system make coding less dull and more rewarding.
The project is evolving rapidly. If you are interested in technical writing, knowledge management, or AI-assisted development, welcome to check it out on GitHub.
Technical Solution Comparison
Заголовок раздела «Technical Solution Comparison»When defining the solution, we compared multiple technical approaches:
1. image-syncer (final choice)
Заголовок раздела «1. image-syncer (final choice)»- Incremental sync: only synchronizes changed image layers, significantly reducing network transfer
- Resume support: synchronization can resume after network interruptions
- Concurrency control: supports configurable concurrency to improve large image sync efficiency
- Robust error handling: built-in retry mechanism for failures (3 times by default)
- Lightweight deployment: single binary with no dependencies
- Multi-registry support: compatible with Docker Hub, Azure ACR, Harbor, and more
2. Docker CLI
Заголовок раздела «2. Docker CLI»- No incremental sync support: each run requires pulling the full image content
- Lower efficiency: large network transfer volume and longer execution time
- Simple and easy to use: relies on familiar
docker pull/docker pushcommands
3. Azure CLI
Заголовок раздела «3. Azure CLI»- Higher complexity: requires Azure CLI authentication setup
- Functional limitations:
az acr importis relatively limited - Native integration: integrates well with Azure services
Architecture Design Decisions
Заголовок раздела «Architecture Design Decisions»Decision 1: Set the sync frequency to daily at 00:00 UTC
Заголовок раздела «Decision 1: Set the sync frequency to daily at 00:00 UTC»- Balances image freshness with resource consumption
- Avoids peak business hours and reduces impact on other operations
- Docker Hub images are usually updated after daily builds
Decision 2: Sync all image tags
Заголовок раздела «Decision 2: Sync all image tags»- Maintains full consistency with Docker Hub
- Provides flexible version choices for users
- Simplifies sync logic by avoiding complex tag filtering rules
Decision 3: Store credentials in GitHub Secrets
Заголовок раздела «Decision 3: Store credentials in GitHub Secrets»- Natively supported by GitHub Actions with strong security
- Simple to configure and easy to manage and maintain
- Supports repository-level access control
Risk Assessment and Mitigation
Заголовок раздела «Risk Assessment and Mitigation»Risk 1: Azure ACR credential leakage
Заголовок раздела «Risk 1: Azure ACR credential leakage»- Use GitHub Secrets for encrypted storage
- Rotate ACR passwords regularly
- Limit ACR account permissions to push-only
- Monitor ACR access logs
Risk 2: Sync failures causing image inconsistency
Заголовок раздела «Risk 2: Sync failures causing image inconsistency»- image-syncer includes a built-in incremental sync mechanism
- Automatic retry on failure (3 times by default)
- Detailed error logs and failure notifications
- Resume support
Risk 3: Excessive resource consumption
Заголовок раздела «Risk 3: Excessive resource consumption»- Incremental sync reduces network transfer
- Configurable concurrency (
10in the current setup) - Monitor the number and size of synchronized images
- Run synchronization during off-peak hours
Core Solution
Заголовок раздела «Core Solution»We use an automated GitHub Actions + image-syncer solution to synchronize images from Docker Hub to Azure ACR.
Implementation Steps
Заголовок раздела «Implementation Steps»1. Preparation
Заголовок раздела «1. Preparation»- Create or confirm an Azure Container Registry in Azure Portal
- Create ACR access credentials (username and password)
- Confirm access permissions for the Docker Hub image repository
2. Configure GitHub Secrets
Заголовок раздела «2. Configure GitHub Secrets»Add the following secrets in the GitHub repository settings:
- AZURE_ACR_USERNAME: Azure ACR username
- AZURE_ACR_PASSWORD: Azure ACR password
3. Create the GitHub Actions workflow
Заголовок раздела «3. Create the GitHub Actions workflow»Configure the workflow in .github/workflows/sync-docker-acr.yml:
- Scheduled trigger: every day at 00:00 UTC
- Manual trigger: supports
workflow_dispatch - Extra trigger: run when the
publishbranch receives a push (for fast synchronization)
4. Workflow execution flow
Заголовок раздела «4. Workflow execution flow»| Sequence | Participant | Action | Description |
|---|---|---|---|
| 1 | GitHub Actions | Trigger workflow | Triggered by schedule, manual run, or a push to the publish branch |
| 2 | GitHub Actions → image-syncer | Download and run the sync tool | Enter the actual sync phase |
| 3 | image-syncer → Docker Hub | Fetch image manifests and tag list | Read source repository metadata |
| 4 | image-syncer → Azure ACR | Fetch existing image information from the target repository | Determine the current target-side state |
| 5 | image-syncer | Compare source and target differences | Identify image layers that need to be synchronized |
| 6 | image-syncer → Docker Hub | Pull changed image layers | Transfer only the content that needs updating |
| 7 | image-syncer → Azure ACR | Push changed image layers | Complete incremental synchronization |
| 8 | image-syncer → GitHub Actions | Return synchronization statistics | Includes results, differences, and error information |
| 9 | GitHub Actions | Record logs and upload artifacts | Useful for follow-up auditing and troubleshooting |
GitHub Actions Workflow Implementation
Заголовок раздела «GitHub Actions Workflow Implementation»Here is the actual workflow configuration in use (.github/workflows/sync-docker-acr.yml):
name: Sync Docker Image to Azure ACR
on: schedule: - cron: "0 0 * * *" # Every day at 00:00 UTC workflow_dispatch: # Manual trigger push: branches: [publish]
permissions: contents: read
jobs: sync: runs-on: ubuntu-latest
steps: - name: Checkout code uses: actions/checkout@v4
- name: Download image-syncer run: | # Download the image-syncer binary wget https://github.com/AliyunContainerService/image-syncer/releases/download/v1.5.5/image-syncer-v1.5.5-linux-amd64.tar.gz tar -zxvf image-syncer-v1.5.5-linux-amd64.tar.gz chmod +x image-syncer
- name: Create auth config run: | # Generate the authentication configuration file (YAML format) cat > auth.yaml <<EOF hagicode.azurecr.io: username: "${{ secrets.AZURE_ACR_USERNAME }}" password: "${{ secrets.AZURE_ACR_PASSWORD }}" EOF
- name: Create images config run: | # Generate the image synchronization configuration file (YAML format) cat > images.yaml <<EOF docker.io/newbe36524/hagicode: hagicode.azurecr.io/hagicode EOF
- name: Run image-syncer run: | # Run synchronization (using the newer --auth and --images parameters) ./image-syncer --auth=./auth.yaml --images=./images.yaml --proc=10 --retries=3
- name: Upload logs if: always() uses: actions/upload-artifact@v4 with: name: sync-logs path: image-syncer-*.log retention-days: 7Configuration Details
Заголовок раздела «Configuration Details»1. Trigger conditions
Заголовок раздела «1. Trigger conditions»- Scheduled trigger:
cron: "0 0 * * *"- runs every day at 00:00 UTC - Manual trigger:
workflow_dispatch- allows users to run it manually in the GitHub UI - Push trigger:
push: branches: [publish]- triggered when the publish branch receives a push (for fast synchronization)
2. Authentication configuration (auth.yaml)
Заголовок раздела «2. Authentication configuration (auth.yaml)»hagicode.azurecr.io: username: "${{ secrets.AZURE_ACR_USERNAME }}" password: "${{ secrets.AZURE_ACR_PASSWORD }}"3. Image sync configuration
Заголовок раздела «3. Image sync configuration»docker.io/newbe36524/hagicode: hagicode.azurecr.io/hagicodeThis configuration means synchronizing all tags from docker.io/newbe36524/hagicode to hagicode.azurecr.io/hagicode
4. image-syncer parameters
Заголовок раздела «4. image-syncer parameters»--auth=./auth.yaml: path to the authentication configuration file--images=./images.yaml: path to the image synchronization configuration file--proc=10: set concurrency to10--retries=3: retry failures3times
GitHub Secrets Configuration Checklist
Заголовок раздела «GitHub Secrets Configuration Checklist»Configure the following in Settings → Secrets and variables → Actions in the GitHub repository:
| Secret Name | Description | Example Value | How to Get It |
|---|---|---|---|
| AZURE_ACR_USERNAME | Azure ACR username | hagicode | Azure Portal → ACR → Access keys |
| AZURE_ACR_PASSWORD | Azure ACR password | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | Azure Portal → ACR → Access keys → Password |
Usage Instructions
Заголовок раздела «Usage Instructions»1. Manually trigger synchronization
Заголовок раздела «1. Manually trigger synchronization»- Open the
Actionstab of the GitHub repository - Select the
Sync Docker Image to Azure ACRworkflow - Click the
Run workflowbutton - Choose the branch and click
Run workflowto confirm
2. View synchronization logs
Заголовок раздела «2. View synchronization logs»- Click a specific workflow run record on the
Actionspage - View the execution logs for each step
- Download the
sync-logsfile from theArtifactssection at the bottom of the page
3. Verify synchronization results
Заголовок раздела «3. Verify synchronization results»# Log in to Azure ACRaz acr login --name hagicode
# List images and their tagsaz acr repository show-tags --name hagicode --repository hagicode --output tableNotes and Best Practices
Заголовок раздела «Notes and Best Practices»1. Security recommendations
Заголовок раздела «1. Security recommendations»- Rotate Azure ACR passwords regularly (recommended every 90 days)
- Use a dedicated ACR service account with push-only permissions
- Monitor ACR access logs to detect abnormal access in time
- Do not output credentials in logs
- Do not commit credentials to the code repository
2. Performance optimization
Заголовок раздела «2. Performance optimization»- Adjust the
--procparameter: tune concurrency based on network bandwidth (recommended5-20) - Monitor synchronization time: if it takes too long, consider reducing concurrency
- Clean up logs regularly: set a reasonable
retention-daysvalue (7days in the current setup)
3. Troubleshooting
Заголовок раздела «3. Troubleshooting»Issue 1: Authentication failed
Заголовок раздела «Issue 1: Authentication failed»Error: failed to authenticate to hagicode.azurecr.ioSolution:
- Check whether GitHub Secrets are configured correctly
- Verify whether the Azure ACR password has expired
- Confirm whether the ACR service account permissions are correct
Issue 2: Network timeout
Заголовок раздела «Issue 2: Network timeout»Error: timeout waiting for responseSolution:
- Check network connectivity
- Reduce concurrency (
--procparameter) - Wait for the network to recover and trigger the workflow again
Issue 3: Incomplete image synchronization
Заголовок раздела «Issue 3: Incomplete image synchronization»Warning: some tags failed to syncSolution:
- Check the synchronization logs to identify failed tags
- Manually trigger the workflow to synchronize again
- Verify that the source image on Docker Hub is working properly
4. Monitoring and alerts
Заголовок раздела «4. Monitoring and alerts»- Regularly check the
Actionspage to confirm workflow run status - Configure GitHub notifications to receive workflow failure alerts promptly
- Monitor Azure ACR storage usage
- Regularly verify tag consistency
Frequently Asked Questions and Solutions
Заголовок раздела «Frequently Asked Questions and Solutions»Q1: How do I sync specific tags instead of all tags?
Заголовок раздела «Q1: How do I sync specific tags instead of all tags?»Modify the images.yaml configuration file:
# Sync only the latest and v1.0 tagsdocker.io/newbe36524/hagicode:latest: hagicode.azurecr.io/hagicode:latestdocker.io/newbe36524/hagicode:v1.0: hagicode.azurecr.io/hagicode:v1.0Q2: How do I sync multiple image repositories?
Заголовок раздела «Q2: How do I sync multiple image repositories?»Add multiple lines in images.yaml:
docker.io/newbe36524/hagicode: hagicode.azurecr.io/hagicodedocker.io/newbe36524/another-image: hagicode.azurecr.io/another-imageQ3: How do I retry after a synchronization failure?
Заголовок раздела «Q3: How do I retry after a synchronization failure?»- Automatic retry: image-syncer includes a built-in retry mechanism (
3times by default) - Manual retry: click
Re-run all jobson the GitHub Actions page
Q4: How do I view detailed synchronization progress?
Заголовок раздела «Q4: How do I view detailed synchronization progress?»- View real-time logs on the
Actionspage - Download the
sync-logsartifact to see the full log file - The log file includes the synchronization status and transfer speed for each tag
Q5: How long does synchronization take?
Заголовок раздела «Q5: How long does synchronization take?»- Initial full synchronization: typically takes
10-30minutes depending on image size - Incremental synchronization: usually
2-5minutes if image changes are small - Time depends on network bandwidth, image size, and concurrency settings
Suggested Enhancements
Заголовок раздела «Suggested Enhancements»1. Add synchronization notifications
Заголовок раздела «1. Add synchronization notifications»Add a notification step to the workflow:
- name: Notify on success if: success() run: | echo "Docker images synced successfully to Azure ACR"2. Implement image tag filtering
Заголовок раздела «2. Implement image tag filtering»Add tag filtering logic to the workflow:
- name: Filter tags run: | # Sync only tags that start with v echo "docker.io/newbe36524/hagicode:v* : hagicode.azurecr.io/hagicode:v*" > images.yaml3. Add a synchronization statistics report
Заголовок раздела «3. Add a synchronization statistics report»- name: Generate report if: always() run: | echo "## Sync Report" >> $GITHUB_STEP_SUMMARY echo "- Total tags: $(grep -c 'synced' image-syncer-*.log)" >> $GITHUB_STEP_SUMMARY echo "- Sync time: ${{ steps.sync.outputs.duration }}" >> $GITHUB_STEP_SUMMARYConclusion
Заголовок раздела «Conclusion»With the method introduced in this article, we successfully implemented automated image synchronization from Docker Hub to Azure ACR. This solution uses the scheduled and manual trigger capabilities of GitHub Actions together with the incremental synchronization and error-handling features of image-syncer to ensure timely and consistent image synchronization.
We also discussed security best practices, performance optimization, troubleshooting, and other related topics to help users better manage and maintain this synchronization mechanism. We hope this article provides valuable reference material for developers who need to deploy Docker images in Azure environments.
References
Заголовок раздела «References»- HagiCode project GitHub repository
- image-syncer official documentation
- Azure Container Registry official documentation
- GitHub Actions official documentation
Reader Interaction
Заголовок раздела «Reader Interaction»Thank you for reading. If you found this article useful, please click the like button below 👍 so more people can discover it.
AI Assistance Disclosure
Заголовок раздела «AI Assistance Disclosure»This content was created with AI-assisted collaboration, reviewed by me, and reflects my own views and position.
Metadata
Заголовок раздела «Metadata»- Author: newbe36524
- Article URL: https://hagicode.com/blog/2026/01/25/how-to-sync-docker-hub-to-azure-acr-with-github
- Copyright: Unless otherwise stated, all articles on this blog are licensed under BY-NC-SA. Please include attribution when reprinting.