Skip to content

fix(docker): make Tentacle images OCI-compliant (FD-492)#1259

Draft
todthomson wants to merge 5 commits into
mainfrom
eft/tod/fix/FD-492-OCI-compliance-etc
Draft

fix(docker): make Tentacle images OCI-compliant (FD-492)#1259
todthomson wants to merge 5 commits into
mainfrom
eft/tod/fix/FD-492-OCI-compliance-etc

Conversation

@todthomson

@todthomson todthomson commented Jun 18, 2026

Copy link
Copy Markdown
Member

Background

Customer FD-492 (Zendesk 209584, ARUP Laboratories) reported that the octopusdeploy/tentacle Docker image is not OCI compliant: Podman rejects it when it is used as a base image (FROM octopusdeploy/tentacle …).

The root cause is not Dockerfile content and not the Debian 11→12 base-image upgrade (#1218 / EFT-3311) — that PR does not touch the manifest format, and building the old vs new image locally shows no difference. The actual problem is inconsistent/mixed manifest media types produced by the build/push pipeline. Docker tolerates this; strict OCI clients like Podman do not.

What Octopus Server actually does (verified in the OctopusDeploy repo)

The triage note claimed Server "fixed the same issue in Jan 2026." I checked the Server repo history directly and that framing is not accurate. There is no oci-mediatypes/--provenance flag combination anywhere in Server's history (git log -S finds zero hits). Instead, Server builds its Linux image single-architecture (linux/amd64) with the classic Docker builder (DockerTasks.DockerBuild + DockerTasks.DockerPush, nuke-build/Build.DockerImages.cs), producing one self-consistent Docker schema2 manifest with no manifest list and no attestation index. Server avoids the problem by never producing a multi-arch/attestation manifest, rather than by fixing one with flags.

Why this PR uses buildx flags instead of copying Server

The Tentacle Kubernetes agent image is genuinely multi-arch (linux/arm64,linux/amd64) and therefore must be built with buildx and a manifest list — it can't adopt Server's single-arch classic-build approach without dropping arm64. For a multi-arch buildx image, the correct equivalent remedy is to force a single OCI media type and drop the attestation index.

Manifest evidence (verified against the published registry)

octopusdeploy/tentacle:latest (the customer's image) — confirmed two distinct OCI violations:

  1. The OCI index mixes manifest formats:

    Platform Manifest mediaType
    linux/amd64 application/vnd.oci.image.manifest.v1+json (OCI — buildx)
    windows/amd64 application/vnd.docker.distribution.manifest.v2+json (Docker schema2 — classic docker build/push)

    A strict OCI consumer rejects an OCI index that references a Docker-schema2 manifest.

  2. Even the linux/amd64 manifest mixes layer media types — application/vnd.docker.image.rootfs.diff.tar.gzip ×4 (inherited debian base layers) + application/vnd.oci.image.layer.v1.tar+gzip ×8 (new layers). This is the literal "mixes two layer format standards", normalized by oci-mediatypes=true.

kubernetes-agent-tentacle:latest (this repo's image) — current published index contains 4 manifests: arm64, amd64, plus two unknown/unknown attestation-manifest entries (buildx provenance). Its per-platform layers are already uniformly OCI, so here the defect is purely the attestation index — removed by disabling default attestations (BUILDX_NO_DEFAULT_ATTESTATIONS=1). (Per-platform layer types verified all-OCI.)

Changes

  1. Build the Kubernetes agent image with consistent OCI media types (build/Build.Pack.cs)

    • On push, use --output type=image,oci-mediatypes=true,push=true and BUILDX_NO_DEFAULT_ATTESTATIONS=1 so the whole manifest uses a single OCI media type with no attestation index.
    • The local --load path (used by tests/dev) is unchanged.
  2. Modernize image labels across all four Dockerfiles

    • Replace the deprecated org.label-schema.* namespace (retired 2016) with the standard org.opencontainers.image.* annotation keys.
    • Use the SPDX identifier Apache-2.0 for the license.

⚠️ Follow-up required (out of scope for this repo)

The customer-reported image, octopusdeploy/tentacle (docker/linux/Dockerfile), is amd64-only on Linux but published in a multi-platform tag alongside the Windows image, and is built in the TeamCity pipeline, not in this repo's NUKE build. Closing FD-492 for that image requires, in TeamCity: (a) build/push the Linux image with oci-mediatypes=true so its layers are uniformly OCI, and (b) assemble the multi-platform tag so the Windows manifest is also OCI (otherwise the OCI index keeps referencing a Docker-schema2 manifest). This PR fixes the Kubernetes agent image (built here) and the shared label metadata.

Testing notes

  • dotnet build build/_build.csproj succeeds.
  • Verify the pushed manifest with docker buildx imagetools inspect --raw <tag>: the index should contain only the two platform manifests (no unknown/unknown attestation manifests), and every layer mediaType should be application/vnd.oci.image.layer.v1.tar+gzip. Plus a podman pull / FROM smoke test.

🤖 Generated with Claude Code


Note (review follow-up): the attestation switch is standardised on BUILDX_NO_DEFAULT_ATTESTATIONS=1 to match the docker buildx bake step in OctopusDeploy/TeamCity-Configuration#112 (identical across buildx build and bake, covers all default attestations, and avoids a post-PATH CLI flag).


OCI annotations (review follow-up): in addition to the Dockerfile LABELs (which set org.opencontainers.image.* on the image config), the k8s agent build now also stamps those annotations onto the image index and each platform manifest via the buildx exporter annotation-index.* / annotation.* options — the spec-preferred location registries/OCI tooling read. Verified locally on a multi-arch build. The linux octopusdeploy/tentacle :latest index is assembled by a separate docker manifest create step (TeamCity-Configuration), so its index annotations are deferred to the manifest-step follow-up (switching to docker buildx imagetools create --annotation).

@todthomson todthomson force-pushed the eft/tod/fix/FD-492-OCI-compliance-etc branch from 8b1e093 to a909c62 Compare June 18, 2026 12:07
Strict OCI clients such as Podman reject the Tentacle Kubernetes agent
image when it is used as a base image: buildx emits a manifest that mixes
Docker and OCI layer media types and wraps it in an OCI index containing
provenance attestation manifests.

- Build the Kubernetes agent image (which must be multi-arch, so it has to
  use buildx) with `type=image,oci-mediatypes=true,push=true` and
  `--provenance=false`, so the whole manifest uses a single, consistent OCI
  media type with no attestation index.
- Replace the deprecated `org.label-schema.*` labels with the standard
  `org.opencontainers.image.*` annotation keys across all Dockerfiles, and
  use the SPDX `Apache-2.0` license identifier.

Note: the customer-reported `octopusdeploy/tentacle` (docker/linux) image
is amd64-only and is built in the TeamCity pipeline, not in this repo. Like
Octopus Server's Linux image, the simplest fix there is a classic single-
arch `docker build` (no buildx manifest list / provenance); if that pipeline
uses buildx, apply the same flags as above.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@todthomson todthomson force-pushed the eft/tod/fix/FD-492-OCI-compliance-etc branch from a909c62 to 70a0178 Compare June 23, 2026 01:40
todthomson and others added 2 commits June 23, 2026 11:55
…IONS (FD-492)

Use BUILDX_NO_DEFAULT_ATTESTATIONS=1 instead of --provenance=false so the
k8s agent buildx build here matches the docker buildx bake step in the
TeamCity Linux image build (OctopusDeploy/TeamCity-Configuration#112). The
env var is identical across buildx build and bake, covers all default
attestations (not just provenance), and avoids passing a CLI flag after the
positional build path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…/manifests (FD-492)

The Dockerfile LABELs set org.opencontainers.image.* on the image config;
this also stamps the same metadata as OCI annotations on the image index and
each platform manifest (via the buildx image-exporter annotation-index.* /
annotation.* options), which is the spec-preferred location that registries
and OCI tooling read.

Verified locally that the annotations land on both the index and the
per-platform manifests.

Note: the linux octopusdeploy/tentacle :latest index is assembled by a
separate 'docker manifest create' step (TeamCity-Configuration); annotating
that index is deferred to the manifest-step follow-up that switches it to
'docker buildx imagetools create --annotation'.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@todthomson todthomson marked this pull request as ready for review June 23, 2026 09:08
@todthomson todthomson requested review from a team as code owners June 23, 2026 09:08
@todthomson todthomson marked this pull request as draft June 24, 2026 02:23
Review nit (E14): the org.opencontainers.image.* metadata is duplicated across
the Dockerfile LABELs, the k8s annotations in Build.Pack.cs, and the TeamCity
manifest step. Add short keep-in-sync comments pointing at the sibling
definitions so the duplication doesn't silently drift. Comment-only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ todthomson
❌ Test


Test seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

…FD-492)

Review nit (E16): capture DateTime.UtcNow once and reuse it for both the
BUILD_DATE build arg (feeding the Dockerfile created LABEL) and the created
OCI annotation, so the image config and manifest annotation report the same
instant instead of two UtcNow calls milliseconds apart. Compile-verified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

2 participants