Security flaws in container images can't always wait. Instead of rebuilding or relying on a new base image, you can patch vulnerabilities directly—without disrupting your workflow.
🚀 What you'll learn:
- Scan a container image with Trivy.
- Apply OS-level patches using Copacetic.
- Push the patched image to a container registry.
By the end, you'll know how to quickly patch container images and keep your deployments secure with minimal effort.
Prerequisites
Before you begin, ensure you have the following installed on your system:
Install Copacetic
On macOS with Homebrew:
brew install copa
On Linux:
# Define variables
VERSION="0.9.0"
URL="https://github.com/project-copacetic/copacetic/releases/download/v${VERSION}/copa_${VERSION}_linux_amd64.tar.gz"
# Download, extract, cleanup, and move copa binary
curl -L -o "copa_${VERSION}_linux_amd64.tar.gz" "$URL" && \
tar -xzf "copa_${VERSION}_linux_amd64.tar.gz" copa && \
rm "copa_${VERSION}_linux_amd64.tar.gz" && \
mv copa /usr/bin/
Future releases can be found, here.
Enable containerd image store
Copacetic uses BuildKit to execute patch commands, think apt update
and apt upgrade
, which are essential for updating and securing container images.
TODO: is this true/ accurate?
https://docs.docker.com/desktop/features/containerd/
The containerd image store simplifies the image-building process by allowing images to be constructed directly within the containerd environment, eliminating the need to start a separate buildkit instance.
Follow these steps to enable the image store:
- In Docker Desktop, go to
Settings
- Select
General
- Then check
Use containerd for pulling and storing images
and clickApply & restart
For cases where the image store isn’t available or suitable, see the Buildkit connection examples.
Patch the container image
Copacetic provides two patching choices: update all packages to their latest versions, or apply targeted patches to fix only vulnerable packages, keeping changes minimal and precise.
Option 1: Update all packages
When you're not concerned with updating specific packages, this is the option you want.
Give it a try: Replace
jduffney/hello-go:0.1.0
with any container image you'd like and use copa to patch it!
Option 2: Update only targeted packages
This process is straightforward: Trivy scans your container image to generate a vulnerability report, identifying specific issues. Copacetic then ingests this report, utilizing the data to apply targeted patches exclusively to the flagged packages, ensuring precise and efficient remediation.
-
Generate a vulnerability report:
trivy image --pkg-types os \ --ignore-unfixed -f json \ -o vulnReport.json \ golang:1.24rc3-alpine3.21
-
Apply targeted patches:
copa patch -i golang:1.24rc3-alpine3.21 \ -r vulnReport.json
Compare Scan Results
Wanna see the patching magic in action? Fire up Trivy to scan your unpatched and patched images—boom, no more vulnerability.
-
Scan the unpatched image:
trivy image --pkg-types os \ --ignore-unfixed \ jduffney/hello-go:0.1.0
-
Scan the patched image:
trivy image --pkg-types os \ --ignore-unfixed \ jduffney/hello-go:0.1.0-patched
At the time of writing, Copacetic successfully patched all 10 vulnerabilities in the jduffney/hello-go:0.1.0
image.
Push the container image
The only thing left to do is to push the freshly patched container image to your registry.
Use docker push
to upload the patched image:
docker tag jduffney/hello-go:0.1.0-patched \
<yourRegistry>/hello-go:0.1.0-patched
docker push <yourRegistry>/hello-go:0.1.0-patched
Note: Replace
<yourRegistry>
with your DockerHub or ghcr information.
🎉 Congrats! Your image is patched and deployment-ready.
Awesome, right? But imagine automatically keeping every image in your registry patched, all the time.
Discover how in the next post. 👈
Top comments (0)