Publishing a DevContainer Feature to GHCR
A custom Feature is only reusable across repos once it's published. This page packages a Feature and pushes it to GitHub Container Registry (GHCR) with the Features CLI, so other projects reference it by OCI path and pin its version like any dependency.
Prerequisites
You need a built Feature and GHCR publish access.
- A Feature with
install.shanddevcontainer-feature.json. - The DevContainer Features publishing action or CLI.
- GHCR write access for the namespace.
Step-by-Step Implementation
- Lay out the Feature in the standard structure.
src/mytool/devcontainer-feature.json
src/mytool/install.sh
- Publish with the official action on release.
- uses: devcontainers/action@v1
with:
publish-features: true
base-path-to-features: ./src
- Reference it by OCI path, pinned.
{ "features": { "ghcr.io/acme/mytool:1": { "version": "1.2.0" } }, "remoteUser": "vscode" }
- Verify a consumer build resolves it.
devcontainer read-configuration --workspace-folder .
Common Pitfalls
Publishing issues are wrong layout, missing permissions, or unpinned consumption.
| Symptom | Root Cause | Remediation |
|---|---|---|
| Publish fails | Wrong Feature layout | Use src/ |
| 403 pushing to GHCR | No package write permission | Grant packages: write to the workflow |
| Consumers get 'latest' silently | Referenced without a version | Pin ghcr.io/org/id to a version |
| Feature not found | Wrong OCI namespace | Match the namespace to your GHCR org |
Conclusion
Publishing a Feature to GHCR turns it into an OCI artifact any project references by path and pins by version — exactly like the official Features. Use the standard src/<id>/ layout and the publishing action, and pin it in consumers so updates are intentional.
FAQ
Why publish to GHCR instead of a local path?
A local path only works within one repo. Publishing to GHCR gives an OCI reference (ghcr.io/org/id) any project can consume and pin, so a Feature authored once is reused across every repo — the same distribution model as the official DevContainer Features.
How do consumers pin my Feature?
They reference it by OCI path with a version, e.g. ghcr.io/acme/mytool:1 plus a version option, and treat bumps as reviewed changes. Pinning keeps a Feature update from silently changing their toolchain, matching base-image and Feature pinning discipline.
What permissions does the publish workflow need?
packages: write for the GHCR namespace, so the action can push the Feature package. Grant it in the workflow's permissions block and ensure the namespace matches your organization, then the publishing action pushes on release.
Related
- Up to Feature & Lifecycle Hook Sequencing — how Features are referenced and ordered.
- Writing a Custom DevContainer Feature — authoring the Feature you publish.
- Container Registry Best Practices for Dev Images — the registry hygiene Features share.