Context
mcr.microsoft.com intermittently WAF-blocks GitHub runner egress IPs ("The request is blocked." HTML response with Ref A/B/C), which fails the uncontrollable container-init image pull in CI jobs that use container.image. There is no way to retry or authenticate that pull from within the workflow.
To work around this, DevSecNinja/dotfiles now mirrors the upstream devcontainer base image into GHCR and consumes it from there:
- Upstream
mcr.microsoft.com/devcontainers/base:debian-12 is mirrored to ghcr.io/devsecninja/devcontainers-base:debian-12 by a scheduled matrix workflow (mirror-base-image.yaml), pinned by digest and kept current by Renovate.
- CI jobs pull the GHCR copy by tag (with
credentials: + packages: read). GHCR has no WAF in front of it.
A reusable Renovate custom manager for digest-pinned container images was also added to this repo's shared preset (.renovate/customManagers.json5, #172).
Goal
Audit all projects (public and private) that still reference the upstream image directly and migrate them to the GHCR mirror.
An org-wide search for mcr.microsoft.com/devcontainers/base:debian surfaces several remaining references (not listed here since some live in private repos).
Per-repo migration checklist
For each repo that pulls the base image in a container: job:
Reference implementation
See DevSecNinja/dotfiles:
.github/workflows/mirror-base-image.yaml (the mirror)
.github/workflows/ci.yaml (consuming the mirror; BASE_IMAGE routed through a validate job output)
Notes
- The mirror is owner-scoped under
ghcr.io/devsecninja/. Private repos consuming it need package read access for their GITHUB_TOKEN/actor.
- Consider promoting the mirror workflow itself into a reusable workflow/template in this repo if more than a couple of projects need it.
Context
mcr.microsoft.comintermittently WAF-blocks GitHub runner egress IPs ("The request is blocked."HTML response with Ref A/B/C), which fails the uncontrollable container-init image pull in CI jobs that usecontainer.image. There is no way to retry or authenticate that pull from within the workflow.To work around this,
DevSecNinja/dotfilesnow mirrors the upstream devcontainer base image into GHCR and consumes it from there:mcr.microsoft.com/devcontainers/base:debian-12is mirrored toghcr.io/devsecninja/devcontainers-base:debian-12by a scheduled matrix workflow (mirror-base-image.yaml), pinned by digest and kept current by Renovate.credentials:+packages: read). GHCR has no WAF in front of it.A reusable Renovate custom manager for digest-pinned container images was also added to this repo's shared preset (
.renovate/customManagers.json5, #172).Goal
Audit all projects (public and private) that still reference the upstream image directly and migrate them to the GHCR mirror.
An org-wide search for
mcr.microsoft.com/devcontainers/base:debiansurfaces several remaining references (not listed here since some live in private repos).Per-repo migration checklist
For each repo that pulls the base image in a
container:job:mcr.microsoft.com/devcontainers/base:debian-12withghcr.io/devsecninja/devcontainers-base:debian-12credentials:block (username: ${{ github.actor }},password: ${{ secrets.GITHUB_TOKEN }}) andpermissions: packages: readenv, expose it via a joboutputsand referenceneeds.<job>.outputs.*—envis not available injobs.<id>.container.imagemirror-base-image.yamlif a new tag/image is required)Reference implementation
See
DevSecNinja/dotfiles:.github/workflows/mirror-base-image.yaml(the mirror).github/workflows/ci.yaml(consuming the mirror;BASE_IMAGErouted through avalidatejob output)Notes
ghcr.io/devsecninja/. Private repos consuming it need package read access for theirGITHUB_TOKEN/actor.