What is Docker Content Trust (DCT)?
Docker Content Trust (DCT) is the original image-signing mechanism for Docker. It uses Notary v1 to sign image manifests and verify them at pull time. In 2026, the industry has largely moved to Cosign / Sigstore, but DCT is still in production at organizations standardized on Docker Hub.
Theory
TL;DR
- DCT signs image manifests with cryptographic keys; the daemon verifies signatures before pull/run.
- Enabled per-process via
DOCKER_CONTENT_TRUST=1. - Backed by Notary v1 (TUF-based: The Update Framework).
- Key hierarchy: root key → repository key → tagging keys → timestamp/snapshot keys.
- Industry trend: moved to Cosign / Sigstore for new work. DCT still valid but no longer the default story.
- Both solve: "is this image really from the publisher I trust, and not tampered with?"
How DCT works
- Publisher generates a root key (cold storage) and repository keys.
- On
docker push, the publisher signs the image manifest. The signature is stored alongside the image in Notary. - On
docker pull, with DCT enabled, the daemon fetches the signature from Notary and verifies it against the publisher's known keys. - If signature is missing or invalid, pull is rejected.
export DOCKER_CONTENT_TRUST=1
docker pull alpine:3.21
# Pulling - succeeds (Alpine images are signed by Docker Inc).
docker pull random/image:1.0
# Error: remote trust data does not exist for random/image:
# notary.docker.io does not have trust data for docker.io/random/imageUnsigned images cannot be pulled when DCT is on.
Pushing signed images
export DOCKER_CONTENT_TRUST=1
docker push myorg/myapp:1.0
# First push prompts for two passphrases:
# - root key passphrase (used once, store cold)
# - repository key passphrase (used for each push)
# Subsequent pushes only ask for the repository key.Keys live in ~/.docker/trust/ by default. Back up the root key. Lose it and you cannot rotate compromised repository keys.
Why teams moved to Cosign / Sigstore
DCT works but has limits:
- Tied to Notary v1 — single backend, integrated with Docker Hub specifically. Other registries had to implement their own Notary servers.
- Operational pain — root key custody is hard. Lost root = repo unrecoverable.
- Limited beyond images — DCT signs Docker images, period. Cosign signs SBOMs, attestations, configs, anything OCI.
- OCI-native vs grafted-on — Cosign uses OCI-native signature artifacts; DCT uses a separate Notary database.
- Keyless signing (Sigstore) — Cosign + Sigstore lets you sign with short-lived OIDC-based identities (no long-lived keys to manage). The 2026 default.
# Cosign (modern)
cosign sign --identity-token=$OIDC_TOKEN myorg/myapp:1.0
cosign verify --certificate-identity=ci@myorg.com myorg/myapp:1.0
# vs DCT (legacy)
DOCKER_CONTENT_TRUST=1 docker push myorg/myapp:1.0New supply-chain security work in 2026 starts with Cosign + Sigstore. DCT is maintained but not extended.
The TUF concept (briefly)
DCT is built on The Update Framework (TUF), designed at NYU to defeat known attacks against software update systems:
- Root role — defines who is trusted. Highest trust, rarely used.
- Targets role — signs the actual targets (images).
- Timestamp role — short-lived signature proving freshness.
- Snapshot role — signs the list of current targets.
This layered key model defends against scenarios like "attacker compromises the registry but cannot mint signatures" or "old version replay".
When to still use DCT
- Docker-Hub-centric workflows where DCT is already integrated and working.
- Compliance requirements that specifically reference DCT (rare; usually they say "signed images" generically).
- Closed ecosystems with no internet access where Sigstore's OIDC cannot be used (DCT can be set up purely offline).
When to use Cosign / Sigstore instead
- New pipelines, full stop.
- Multi-registry workflows.
- Need to sign more than images (SBOMs, attestations, configs).
- Want keyless signing via OIDC (GitHub Actions, GitLab CI).
- OCI-native pipelines.
Common mistakes
Treating DCT as "on by default"
DCT requires DOCKER_CONTENT_TRUST=1 per shell or daemon-wide config. Without it, the daemon happily pulls unsigned images. CI must explicitly set it.
Losing the root key
~/.docker/trust/private/<repo>/.
One key, one backup. Lose it = you cannot revoke repository keys, cannot rotate, cannot recover.
Mixing DCT and Cosign without policy
A repo signed with DCT and Cosign confuses tooling. Pick one approach per repo. If migrating, run both during transition, then retire DCT.
Assuming DCT signs the image content directly
It signs the manifest, which references the layer digests. The signature transitively covers the image. But the layer files themselves are not signed — the manifest is the integrity anchor.
Real-world usage
- Docker Hub workflows: organizations that built around DCT in 2017-2020 still using it for pull-time verification.
- Notary servers: some self-hosted registries (Harbor) integrate Notary v1 for in-cluster DCT.
- Cosign in CI: GitHub Actions + Sigstore keyless signing has become the de-facto default for new open-source images.
- Hybrid: sign with Cosign, verify with admission controllers (Kyverno, OPA Gatekeeper) at K8s admission time.
Follow-up questions
Q: Does DCT verify image content or just the manifest?
A: It verifies the manifest, which contains layer digests. Since digests are content-addressed, manifest signature transitively guarantees layer integrity. Tampering with layers changes their digests, which would invalidate the manifest.
Q: Can I use DCT without Docker Hub?
A: Yes — any registry that has a Notary server (Harbor, JFrog Artifactory). Set DOCKER_CONTENT_TRUST_SERVER to point at the Notary endpoint. Less common than Docker Hub usage.
Q: What is Notary v2?
A: Successor to Notary v1, designed as part of the OCI Notary spec. Different signature format, OCI-native. In practice, the industry coalesced around Cosign/Sigstore instead of Notary v2 for most new work.
Q: How does Cosign differ from DCT in practice?
A: Cosign signatures are stored as OCI artifacts in the same registry (no separate Notary server). Cosign supports keyless signing via OIDC (no key management). Cosign extends to SBOMs, attestations, etc. DCT is image-only and key-based.
Q: (Senior) How would you design image signing for a multi-team production environment?
A: Cosign + Sigstore + admission control. CI builds and signs images with keyless OIDC (GitHub Actions / GitLab CI / Buildkite). Sigstore's Rekor logs the signing event. K8s admission controller (Kyverno, OPA Gatekeeper, or sigstore-policy-controller) checks every pulled image's signature against expected identities. Attestations (SBOM, provenance) signed alongside images. Supplement with vulnerability scans gated at admission. The result: production refuses any image not signed by your CI's OIDC identity, and you have audit trail of every signing event in Rekor.
Examples
Enabling DCT for a CI pipeline
# CI environment variables
DOCKER_CONTENT_TRUST=1
DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE=$REPO_KEY_PASSPHRASE
DOCKER_CONTENT_TRUST_ROOT_PASSPHRASE=$ROOT_KEY_PASSPHRASE
# Build and push (signs automatically)
docker build -t myorg/myapp:1.0 .
docker push myorg/myapp:1.0
# Notary entry created with signature.
# Production pulls with DCT enabled
export DOCKER_CONTENT_TRUST=1
docker pull myorg/myapp:1.0
# Daemon fetches signature, verifies, pulls.Equivalent with Cosign (modern)
# CI: GitHub Actions with OIDC
- uses: sigstore/cosign-installer@v3
- run: |
docker push myorg/myapp:1.0
cosign sign --yes myorg/myapp:1.0
# No keys to manage — Sigstore issues a short-lived cert tied to your GHA workflow's OIDC identity.
# Verification anywhere
cosign verify \
--certificate-identity=https://github.com/myorg/myrepo/.github/workflows/build.yml@refs/heads/main \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
myorg/myapp:1.0The modern flow has no long-lived keys, OIDC issuer pinning, and works across any OCI registry.
Notary CLI for inspection
# See trust data for an image
notary -s https://notary.docker.io list docker.io/library/alpine
NAME DIGEST SIZE (BYTES) ROLE
3.21 sha256:abc123... 1234 targets
3.20 sha256:def456... 1234 targetsDirectly inspect what is signed and by whom. Useful for audits.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.
Comments
No comments yet