Skip to content

Add Radius.Compute/containerImages resource type and Kubernetes Terraform recipe#151

Draft
willdavsmith wants to merge 7 commits into
mainfrom
feat/containerimages-resource-type
Draft

Add Radius.Compute/containerImages resource type and Kubernetes Terraform recipe#151
willdavsmith wants to merge 7 commits into
mainfrom
feat/containerimages-resource-type

Conversation

@willdavsmith
Copy link
Copy Markdown
Contributor

@willdavsmith willdavsmith commented May 13, 2026

Summary

Adds a new Radius.Compute/containerImages resource type that builds a container image from source and pushes it to a remote registry, enabling source-to-running-app developer workflows in Radius without a host Docker socket, a privileged Pod, or per-node host preparation.

The Kubernetes Terraform recipe drives a rootless BuildKit sidecar (provided by the dynamic-rp Helm chart in radius-project/radius#11882) via the buildctl CLI.

What's in this PR

  • Compute/containerImages/containerImages.yaml — resource type schema (API version 2025-08-01-preview)
  • Compute/containerImages/recipes/kubernetes/terraform/{main,var}.tf — Kubernetes Terraform recipe
  • Compute/containerImages/test/app.bicep — test fixture
  • Compute/containerImages/README.md — architecture, prerequisites, multi-arch builds, lifecycle/destroy semantics, local testing

Coordination

Companion PR in radius-project/radius adds the BuildKit sidecar to the dynamic-rp chart. Both should land together; this one is reviewable independently.

Design

Design review for this feature was completed prior to this PR.

Notable details

  • Shell-injection safety. The recipe uses local-exec to invoke buildctl. Every interpolated value (registry, resource name, tag, dockerfile path, build context, platforms) is gated by a precondition block on a validate_inputs terraform_data resource that the build resource depends on. Inputs failing the regex are rejected at plan time.
  • Destroy semantics. terraform destroy removes the resource from state but does not delete the pushed image from the registry. Documented explicitly in the README (different registries have very different deletion semantics; image cleanup is an operator-side retention concern).
  • Multi-arch. build.platforms is supported and uses BuildKit cross-compilation. README includes a working BUILDPLATFORM/TARGETPLATFORM Dockerfile example. There is intentionally no QEMU/binfmt fallback.
  • Git context tag requirement. When build.context is a git URL, an explicit properties.tag is required (otherwise properties.image would be stable across commits and Kubernetes wouldn't roll the Deployment).

Testing

  • terraform validate passes on the recipe.
  • README's "Local testing" section documents the manual end-to-end flow.
  • Full CI integration is deferred — see follow-up issue (will link).

Follow-ups

Adds a new resource type that builds a container image from source and
pushes it to a remote registry. The Kubernetes Terraform recipe drives
a rootless BuildKit sidecar (provided by the dynamic-rp Helm chart) via
the buildctl CLI, with input validation precondition blocks guarding
the local-exec command line against shell injection.

Includes:
- Compute/containerImages/containerImages.yaml resource type schema
- Compute/containerImages/recipes/kubernetes/terraform/{main,var}.tf
- Compute/containerImages/test/app.bicep fixture
- README covering architecture, lifecycle/destroy semantics,
  multi-arch builds, prerequisites, and local testing

Coordinates with radius-project/radius PR for the chart sidecar.
Replace per-resource registry override and the implicit chart-mounted
config.json with a required `secretName` property pointing at a
Radius.Security/secrets in the application's namespace. The recipe
reads USERNAME and PASSWORD via the kubernetes_secret_v1 data source
and stages a Docker config.json that buildctl picks up via DOCKER_CONFIG.
Default platforms to ["linux/amd64", "linux/arm64"]. Update test app to
declare the secret and reference it.
Will revert once we identify why the GHCR push is getting 403.
The Radius.Security/secrets recipe double-encodes data values (it
base64-encodes before assigning to kubernetes_secret.data, which
the TF provider also encodes). Decode once on read so the GHCR
auth header is the actual token, not base64 of it.

Also reverts the temporary DOCKER_CONFIG diagnostic echo.
Extends Radius.Security/secrets with a dockerconfigjson kind (assembles
a Docker config.json blob and emits a kubernetes.io/dockerconfigjson
typed Secret via binary_data), and Radius.Compute/containers with an
imagePullSecrets property (threaded into the Deployment's
template.spec).

Updates Radius.Compute/containerImages to read .dockerconfigjson
directly from the named Secret — one symmetric Secret used by both
the build push and kubelet's pod pull. Drops the previous
USERNAME/PASSWORD assembly and the base64decode workaround.
Drop the developer-facing secretName property and the requirement
that the developer declare a Radius.Security/secrets resource for
registry credentials. The platform engineer now provisions a single
dockerconfigjson Secret in radius-system and points the recipe at
it via two new recipe parameters (registrySecretName,
registrySecretNamespace). The recipe materializes a per-resource
pull Secret in the application namespace and exposes its name via
the new readOnly imagePullSecretName output, which the developer
references from Radius.Compute/containers.imagePullSecrets.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant