ENH: Mirror dockcross images to GHCR for reliable Python wheel builds#124
ENH: Mirror dockcross images to GHCR for reliable Python wheel builds#124hjmjohnson merged 3 commits intomainfrom
Conversation
Python wheel CI builds pull large dockcross/manylinux container images (~1-2 GB) from Docker Hub and Quay.io on every run. These pulls intermittently fail with "unexpected EOF" or Docker Hub rate limiting (401/429), causing wheel builds to fail across all remote modules. Add a scheduled workflow that mirrors the pinned dockcross images to GHCR (ghcr.io/insightsoftwareconsortium/), which has much better connectivity from GitHub Actions runners (same network). Add pre-pull steps to the Linux x64 and ARM build jobs that: 1. Try pulling from the GHCR mirror first 2. Fall back to the original Docker Hub / Quay.io source 3. Retry up to 3 times with backoff 4. Tag the GHCR image with the original name so the downstream ITKPythonPackage build scripts find it already cached This eliminates transient Docker image pull failures that have been causing sporadic Python wheel build failures across ~55 remote modules. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Temporarily point python-build-workflow at the ghcr-mirror-dockcross-images branch of ITKRemoteModuleBuildTestPackageAction to test the pre-pull step with GHCR fallback logic. See: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction#124
Temporarily point python-build-workflow at the ghcr-mirror-dockcross-images branch of ITKRemoteModuleBuildTestPackageAction to test the pre-pull step with GHCR fallback logic. See: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction#124
Temporarily point python-build-workflow at the ghcr-mirror-dockcross-images branch of ITKRemoteModuleBuildTestPackageAction to test the pre-pull step with GHCR fallback logic. See: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction#124
Temporarily point python-build-workflow at the ghcr-mirror-dockcross-images branch of ITKRemoteModuleBuildTestPackageAction to test the pre-pull step with GHCR fallback logic. See: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction#124
Temporarily point python-build-workflow at the ghcr-mirror-dockcross-images branch of ITKRemoteModuleBuildTestPackageAction to test the pre-pull step with GHCR fallback logic. See: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction#124
Temporarily point python-build-workflow at the ghcr-mirror-dockcross-images branch of ITKRemoteModuleBuildTestPackageAction to test the pre-pull step with GHCR fallback logic. See: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction#124
Temporarily point python-build-workflow at the ghcr-mirror-dockcross-images branch of ITKRemoteModuleBuildTestPackageAction to test the pre-pull step with GHCR fallback logic. See: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction#124
Temporarily point python-build-workflow at the ghcr-mirror-dockcross-images branch of ITKRemoteModuleBuildTestPackageAction to test the pre-pull step with GHCR fallback logic. See: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction#124
Temporarily point python-build-workflow at the ghcr-mirror-dockcross-images branch of ITKRemoteModuleBuildTestPackageAction to test the pre-pull step with GHCR fallback logic. See: InsightSoftwareConsortium/ITKRemoteModuleBuildTestPackageAction#124
Testing status across 9 remote modulesNine remote module PRs have been pointed at Pre-pull fallback results (GHCR miss → Docker Hub/Quay.io)From SkullStrip run 23880135873 (first test) and run 23880137293:
The pre-pull step correctly:
Module test PRs
Expected benefits once GHCR images are populated
Next steps
|
|
@thewtex I'm wondering if this improvement should be considered for a new v5.4.5 tag? |
The pre-pull step was hardcoding v5.4.x image tags, but modules using v6.0b02 defaults pull different images (20260203-3dfb3ff for x64, 2025.08.12-1 for aarch64). The pre-pull cached the wrong image and the actual build script still hit Docker Hub without caching. Fetch dockcross-manylinux-set-vars.sh from the same ITKPythonPackage tag the build will use, then source it to get the correct IMAGE_TAG and CONTAINER_SOURCE. This ensures the pre-pull step always caches exactly the image the build script will need. Also add v6.0b02 image tags to the GHCR mirror workflow. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add docker.io/dockcross/manylinux_2_28-x64:20250913-6ea98ba used by ITKPythonPackage v6.0b01 (currently only ITKTotalVariation). Complete image tag coverage across all ITKPythonPackage versions: - v5.4.0-v5.4.5: 20240304-9e57d2b (x64), 2024-03-25-9206bd9 (aarch64) - v6.0b01: 20250913-6ea98ba (x64), 2025.08.12-1 (aarch64) - v6.0b02/main: 20260203-3dfb3ff (x64), 2025.08.12-1 (aarch64) - manylinux2014-x64: 20240304-9e57d2b (all versions) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@dzenanz You might be interested in this work. It helps with remote module CI stability. How we deal with tags will be an issue. we might want a new tag v5.4.5.post01 or similar to use to take advantage of this. |
|
Is there any benefit of |
|
@hjmjohnson awesome!!
We could try it for v5.4.6. The packages I see here are https://github.com/orgs/InsightSoftwareConsortium/packages GHCR has a limit of 500 MB on for private images. I assume we will hit this fairly quick. Can they be made public? We could use this. Also, for awareness, there is a GitHub Action dedicated to help with this that does retry with exponential backoff, used in ITK-Wasm: |
|
@thewtex I don't have permission to make the items public. Would you make the tag? I don't understand how tagging works across the various ITK related repos. We don't have a v5.4.6 tag in ITK, but one may be planned. |
|
@hjmjohnson I'll make a call for additional patches for v5.4.6 next week, then tag later in the week. The tag MUST be immutable. Do not create a tag. |

Summary
mirror-dockcross-images.yml) that mirrors all pinned dockcross/manylinux container images toghcr.io/insightsoftwareconsortium/Problem
Python wheel builds across ~55 remote modules intermittently fail due to transient Docker image pull errors:
Error: writing blob: storing blob to file "...": happened during read: unexpected EOFError fetching blob: invalid status code from registry 504 (Gateway Timeout)These failures are caused by pulling ~1-2 GB dockcross images from Docker Hub/Quay.io on every CI run using GitHub Actions shared runners.
How it works
Dynamic image tag resolution
The pre-pull steps fetch
dockcross-manylinux-set-vars.shfrom the same ITKPythonPackage version the build will use (via theitk-python-package-taginput). This ensures the pre-pull caches exactly the image the build script needs, regardless of which ITKPythonPackage version the module targets.Pre-pull with GHCR mirror + fallback
IMAGE_TAGandCONTAINER_SOURCEfrom the ITKPythonPackage build scriptsghcr.io/insightsoftwareconsortium/dockcross-*) — same network as GitHub Actions, fast + reliableEdge cases
itk-python-package-tagrefs (e.g.,release-5.4): works —set-vars.shexists on that branch with the correct tagspython_based_build_scripts): graceful skip — noset-vars.shon that branch, pre-pull exits cleanlyImages mirrored (6 total, covering v5.4.x, v6.0b01, v6.0b02/main)
docker.io/dockcross/manylinux_2_28-x64:20240304-9e57d2bghcr.io/.../dockcross-manylinux_2_28-x64:20240304-9e57d2bdocker.io/dockcross/manylinux_2_28-x64:20250913-6ea98baghcr.io/.../dockcross-manylinux_2_28-x64:20250913-6ea98badocker.io/dockcross/manylinux_2_28-x64:20260203-3dfb3ffghcr.io/.../dockcross-manylinux_2_28-x64:20260203-3dfb3ffdocker.io/dockcross/manylinux2014-x64:20240304-9e57d2bghcr.io/.../dockcross-manylinux2014-x64:20240304-9e57d2bquay.io/pypa/manylinux_2_28_aarch64:2024-03-25-9206bd9ghcr.io/.../dockcross-manylinux_2_28-aarch64:2024-03-25-9206bd9quay.io/pypa/manylinux_2_28_aarch64:2025.08.12-1ghcr.io/.../dockcross-manylinux_2_28-aarch64:2025.08.12-1Testing
Tested across 9 remote modules by pointing their
python-build-workflowat@ghcr-mirror-dockcross-images. See test results comment.Pre-pull fallback path verified (GHCR miss → Docker Hub/Quay.io):
GHCR pull path verified (5 of 6 images already populated):
20240304-9e57d2b(x64),20260203-3dfb3ff(x64),20240304-9e57d2b(2014),2024-03-25-9206bd9(aarch64),2025.08.12-1(aarch64) — all in GHCR20250913-6ea98ba(x64, v6.0b01) — pending pushPost-merge steps
Mirror dockcross images to GHCRworkflow to populate any missing images🤖 Generated with Claude Code