Seal My Container
Container-to-container sealing for your own private images.
Seal My Container is for the case where the container you want sealed is one you built, not a public upstream image. The customer's existing image-build pipeline produces an image with vulnerable OS-level packages (and possibly application artifacts) inside. Seal My Container takes that built image, replaces the vulnerable packages, and pushes the sealed result back to the same tag — overwriting the original. From the perspective of every deployment that already pulls your-registry/your-app:1.2.3, the tag is the same; only the contents are now sealed.
The mechanism is a single CLI command: seal image fix. It pulls the source image, rebuilds it as a one-stage FROM <source> Dockerfile with the seal step inside, and pushes the result back to the same tag (or to a different tag, if you pass --tag). From the rest of your pipeline's perspective, it's a post-build step that takes an image in and returns a sealed image out, in place.
When to use this
The Seal product lineup distinguishes three container-shaped products:
Seal Base Images when the image you want sealed is a public upstream that Seal has already sealed (Python, OpenJDK, Elasticsearch, and so on). You pull the sealed counterpart, your build uses it. Lowest friction; no per-image work.
Seal My Container (this chapter) when the image is one you built yourself. The image is private to your tenant, not a public upstream, and you need the OS packages inside it sealed without rewriting your
Dockerfileor migrating distributions.Seal Vendor Apps when the image is one a vendor ships and you run as-is (a Kafka image from Confluent, a database image from Oracle). Seal cannot redistribute a copy because of licensing; the workflow is different.
For application packages inside your own image, the canonical path is still to seal at build time using the Seal CLI in CI/CD, where each ecosystem's package manager and lockfile are present. seal image fix also seals JAR files anywhere in the image's filesystem alongside the OS layer, which makes it the right tool for cases where the JARs are already built and you cannot reach back into the source build (vendor-shipped JARs, third-party deliveries, and so on).
How seal image fix works
seal image fix worksyour CI / a scheduled runner / a developer
|
seal image fix <image>
|
┌──────────────────────────────────────────────────────┐
│ docker pull <image> │ from the registry
│ generate seal.dockerfile │ FROM <image>, RUN seal fix --os, RUN seal fix --fs java /
│ docker build -t <same-tag> │ both seal steps run inside this build
│ docker push <same-tag> │ overwrite the original tag
└──────────────────────────────────────────────────────┘The CLI orchestrates a small set of docker calls (pull, build, push, plus an inspect to capture metadata) on the host it runs on. Docker must be installed on that host; the CLI invokes the docker binary directly. The seal steps themselves run inside the build, in layers added on top of the pulled image. The OS-layer step is the same seal fix --os logic documented in Seal OS in CI/CD; the JAR-sealing step runs seal fix --fs java / to recursively rewrite any vulnerable JAR files anywhere in the image. Both are wrapped in a generated Dockerfile so the build context is reproducible.
The generated Dockerfile uses BuildKit's secret-mount feature to keep SEAL_TOKEN out of the resulting image's layers. BuildKit is enabled by default in recent Docker releases; on older Docker daemons, set DOCKER_BUILDKIT=1 in the environment before running seal image fix.
The token is plumbed in through --secret id=SEAL_TOKEN,env=SEAL_TOKEN. The two SEAL_TOKENs refer to two different things and just happen to share the name: the first is the BuildKit secret's ID (the handle the inner RUN step references), and the second is the host environment variable BuildKit reads the value from. Using the same name for both is the conventional setup.
What it covers
seal image fix seals two layers of a container image:
OS packages installed through
apk,apt/dpkg, ordnf/yum. The package families and per-distribution mechanics are the same as the standaloneseal fix --osdocumented under Seal OS in CI/CD. Distroless images are supported too — the CLI uses a filesystem-level mechanism to seal packages in images where the package-manager binary itself was stripped out.JAR files anywhere in the image's filesystem, sealed via
seal fix --fs java /as the second step of the generated build.
Python wheels can also be sealed inside a container, via seal fix --fs python <path>. The default seal image fix flow does not scan for them automatically; reach for the custom-Dockerfile pattern documented in Seal Vendor Apps when an image carries wheels you want sealed.
For npm dependencies and Go binaries, seal at the application's own build time using the Seal CLI in CI/CD; there is no post-build sealing path for those.
Chapter contents
This chapter is the canonical setup home for Seal My Container.
Authenticating with your container registry: the source-registry and destination-registry credentials Docker needs on the host where
seal image fixruns.The
seal image fixcommand and flags: the full reference, including the required--platformflag and the optional--tag.Implementing the centralized re-seal pipeline: the most common production pattern — a single automation that triggers on registry pushes, seals the image, and pushes the sealed result back.
Renaming packages inside containers: the recommended default — rename sealed packages inside the image so external scanners do not flag them.
Common issues: the failures that come up most often.
Before you start
A built container image. The image is typically based on an
apk,apt, ordnf/yum-managed Linux distribution; distroless images are also supported.Docker installed on the host where
seal image fixruns. The CLI invokes thedockerbinary directly. BuildKit is the build engine used; it is the default in current Docker releases.The host authenticated to the registry holding the image; see Authenticating with your container registry. The typical setup uses one registry for both pull and push.
The Seal CLI installed on the host. The same binary used elsewhere in Seal; no separate install.
SEAL_TOKENandSEAL_PROJECTset in the host's environment.
Related
Seal My Container: the product-family page that frames where this fits among the five Seal products.
Working with Seal My Container: the day-2 operating rhythm once the pipeline is in place. (Documented under "Using the Seal Platform.")
Seal OS in CI/CD: the parallel chapter that runs the same seal step inside a
Dockerfileyou wrote yourself, rather than inside a generated wrapper around a pre-built image.
Last updated