{"id":39557918,"url":"https://github.com/sredevopsorg/multi-arch-docker-github-workflow","last_synced_at":"2026-01-18T07:02:20.609Z","repository":{"id":282999995,"uuid":"950354517","full_name":"sredevopsorg/multi-arch-docker-github-workflow","owner":"sredevopsorg","description":"How to build a Multi-Architecture Docker Image in Github Actions using multiple runners without QEMU","archived":false,"fork":false,"pushed_at":"2025-12-23T21:59:08.000Z","size":59,"stargazers_count":15,"open_issues_count":1,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-25T11:41:57.038Z","etag":null,"topics":["docker","github-actions","github-runners","github-workflows","multiarch-images"],"latest_commit_sha":null,"homepage":"https://sredevops.org/en/kiss-goodbye-to-qemu-unleash-the-power-of-native-github-runners-for-multi-arch-docker-images/","language":"Dockerfile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sredevopsorg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-18T03:08:51.000Z","updated_at":"2025-12-25T00:37:35.000Z","dependencies_parsed_at":"2025-03-18T04:25:35.856Z","dependency_job_id":"09d9236d-e475-42dd-8f93-05743622ff5c","html_url":"https://github.com/sredevopsorg/multi-arch-docker-github-workflow","commit_stats":null,"previous_names":["sredevopsorg/multi-arch-docker-github-workflow"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/sredevopsorg/multi-arch-docker-github-workflow","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sredevopsorg%2Fmulti-arch-docker-github-workflow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sredevopsorg%2Fmulti-arch-docker-github-workflow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sredevopsorg%2Fmulti-arch-docker-github-workflow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sredevopsorg%2Fmulti-arch-docker-github-workflow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sredevopsorg","download_url":"https://codeload.github.com/sredevopsorg/multi-arch-docker-github-workflow/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sredevopsorg%2Fmulti-arch-docker-github-workflow/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28532593,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T00:39:45.795Z","status":"online","status_checked_at":"2026-01-18T02:00:07.578Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["docker","github-actions","github-runners","github-workflows","multiarch-images"],"created_at":"2026-01-18T07:02:20.542Z","updated_at":"2026-01-18T07:02:20.599Z","avatar_url":"https://github.com/sredevopsorg.png","language":"Dockerfile","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Multi-Architecture Docker Build with Native GitHub Runners\n\n## How to build a Multi-Architecture Docker Image in Github Actions using multiple runners without QEMU\n\n\u003ccenter\u003e\u003cimg alt=\"Logo SREDevOps.org\" src=\"https://www.sredevops.org/content/images/2024/11/sredevopsorg.svg\" /\u003e\u003c/center\u003e\n\nCreated by [SREDevOps.org](https://www,sredevops.org) | [@sredevopsorg](https://github.com/sredevopsorg) | [@ngeorger](https://github.com/ngeorger)\n\n[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/11363/badge)](https://www.bestpractices.dev/projects/11363)\n\nBy following these steps and reviewing the workflow file, you can customize and use this multi-architecture build process in your own projects. Happy building!\n\nThis repository demonstrates how to build multi-architecture Docker images (for example, **linux/amd64** and **linux/arm64**) using native GitHub runners instead of QEMU emulation. By leveraging separate native runners for each architecture, you get faster builds and higher fidelity (no emulation quirks) while still producing a single multi-arch image that you can push to GitHub Container Registry (GHCR).\n\n\u003e **Note:** This workflow requires access to both an AMD64 runner (using `ubuntu-latest`) and an ARM64 runner (for example, `ubuntu-24.04-arm`). Make sure your GitHub organization or repository has access to these runners.\n\n\n## Overview\n\nThe workflow is divided into two main jobs:\n\n1. **Build Job:**  \n   - Uses a matrix strategy to build images for each platform separately.\n   - Sets up a Docker context and configures Buildx to build images natively.\n   - Logs into GHCR and builds \u0026 pushes the image by digest.\n   - Exports the digest as an artifact for later use.\n\n2. **Merge Job:**  \n   - Downloads the digests from the build job.\n   - Generates Docker image metadata (tags, labels, and annotations).\n   - Uses Buildx to create a multi-architecture manifest list from the individual images.\n   - Pushes the merged manifest (which tells Docker which image to pull based on the host architecture).\n\nThis two-step process creates a “fat” image that automatically delivers the correct binary for the user’s architecture.\n\n\n## Features\n\n- **Native Builds:** Uses GitHub’s native runners for each platform (no QEMU).\n- **Multi-Arch Manifest:** Automatically merges per-architecture images into one multi-arch image.\n- **Build Caching:** Implements caching to speed up subsequent builds.\n- **OCI Metadata:** Adds labels and annotations for better image provenance.\n- **Concurrency Control:** Uses GitHub Actions concurrency to cancel outdated builds.\n\n\n## Getting Started\n\n### Prerequisites\n\n- A GitHub repository with this workflow set up.\n- Access to GitHub-hosted runners for both **linux/amd64** and **linux/arm64**.\n- A GitHub token (automatically provided as `GITHUB_TOKEN`) with permission to push to GHCR.\n- A valid Dockerfile in the repository root (or modify the workflow’s context as needed).\n\n### Setup\n\n1. **Clone the Repository:**\n\n   ```bash\n   git clone https://github.com/sredevopsorg/multi-arch-docker-github-workflow.git\n   cd multi-arch-docker-github-workflow\n   ```\n\n2. **Review and Customize:**\n\n   - **Dockerfile:**  \n     The provided Dockerfile is a simple example. Customize it as needed for your application or replace it with your own.\n\n   - **Workflow File:**  \n     The GitHub Actions workflow is defined in `.github/workflows/multi-build.yaml`. You can adjust parameters (e.g., caching options, labels, annotations) if needed.\n\n3. **Configure Secrets (if applicable):**\n\n   - By default, the workflow uses the built-in `GITHUB_TOKEN` for authentication to GHCR. If you need to change registry credentials or add additional secrets, set them in your repository’s **Settings \u003e Secrets and Variables**.\n\n\n## How It Works (Step by Step)\n\n### Build Job (Per-Architecture Build)\n\n1. **Prepare Environment:**  \n   The first step in the build job sets an environment variable (`PLATFORM_PAIR`) by replacing any `/` characters in the platform name with `-`. This ensures artifact names are valid.\n\n2. **Checkout Code:**  \n   The repository is checked out using [actions/checkout](https://github.com/actions/checkout).\n\n3. **Generate Docker Metadata:**  \n   The [docker/metadata-action](https://github.com/docker/metadata-action) creates metadata (tags, labels, annotations) based on repository information.\n\n4. **Setup Docker Context and Buildx:**  \n   - A new Docker context (named `builders`) is created.\n   - The [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) is configured to use that context and the specific platform from the matrix (either `linux/amd64` or `linux/arm64`).\n\n5. **Login to GHCR:**  \n   The workflow logs in to GitHub Container Registry using the `GITHUB_TOKEN`.\n\n6. **Build and Push:**  \n   Using [docker/build-push-action](https://github.com/docker/build-push-action), the image is built with the specified platform, labels, and caching options. The image is pushed by digest and the resulting digest is exported.\n\n7. **Artifact Upload:**  \n   The digest file is uploaded as an artifact (named with the platform pair) for use in the next job.\n\n### Merge Job (Manifest Creation)\n\n1. **Download Digests:**  \n   The merge job downloads all the digest artifacts from the build job.\n\n2. **Re-generate Docker Metadata:**  \n   Metadata is generated again to ensure consistency with the built images.\n\n3. **Setup Buildx and Login:**  \n   The job sets up Buildx (this time without a custom context) and logs in to GHCR.\n\n4. **Create Multi-Arch Manifest:**  \n   The workflow runs `docker buildx imagetools create` to merge the images (using the digest files) into a single multi-architecture manifest list. Annotations such as description, creation timestamp, and source URL are added.\n\n5. **Manifest Inspection:**  \n   Finally, the merged image is inspected to verify that it contains the proper platform-specific entries.\n\n\n## Triggering the Workflow\n\n- **Automatic Trigger:**  \n  Pushing changes to the `Dockerfile` or the workflow file (`.github/workflows/multi-build.yaml`) on the `main` branch will automatically trigger the workflow.\n\n- **Manual Trigger:**  \n  You can also trigger the workflow manually using the `workflow_dispatch` event.\n\n\n## How to Use the Built Image\n\nOnce the workflow completes, your multi-architecture image is available in GHCR. For example, if your repository is `ghcr.io/your-org/your-repo`, you can pull the image as follows:\n\n```bash\ndocker pull ghcr.io/your-org/your-repo:latest\n```\n\nDocker will automatically select the correct image based on your host’s CPU architecture.\n\n\n## Contributing\n\nContributions, issues, and feature requests are welcome! Feel free to check [Issues](https://github.com/sredevopsorg/multi-arch-docker-github-workflow/issues) or submit a pull request.\n\n\n## License\n\nThis project is licensed under the [MIT License](LICENSE).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsredevopsorg%2Fmulti-arch-docker-github-workflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsredevopsorg%2Fmulti-arch-docker-github-workflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsredevopsorg%2Fmulti-arch-docker-github-workflow/lists"}