Docker Container Image Security: 13 Best Practices

 

Transcript:

In this video, we will discuss the best practices for securing Docker container images. How can we reduce the risk of attacks on our Docker container images? The short answer is by reducing the attack surface and time spent on detecting the malicious activity. Yeah, but how to do that? Watch and find out.

Keep your container images lean and boring. The smaller the attack surface in your production image, the better. Therefore, try to minimize the number of components that represent a potentially exploitable path. Depending on your application, consider using a minimalistic Linux distro, a distloress image, or even a scratch. Use multi-stage to transfer the app into a final base image. The final image should contain the immutable set of components required for your application to run. No package manager if possible. A package manager in production kills immutability and widens the attack surface. Attackers can use the package manager to install malicious packages with the vulnerabilities. Therefore, if your use case allows to do so, try to use slimbased images without a package manager. Non route and minimum privileges. Running the container as root or giving it a full set of privileges will give the intruders a host level access to container resources and the ability to exercise kernel attacks. So set the unprivileged user and group in the docker file to run the container. Also, if possible, try to avoid using the privileged flag in production because it gives all Linux kernel capabilities to the container. Instead, limit the granted privileges only to those needed by the container. You can first run cap drop all just to be sure and then add the required privileges with the cap at.

Strive towards immutability when possible. Immutability means that the container must correspond to the container image. It means no config tweaks, uh no changes in the privileges, no patches or fixes in the production. If something changes, you rebuild and redeploy the artifact. The key approach to more secure containers in this regard is to use base images with only the essential set of components required by your application and it should be immutable. Also, there shouldn't be any package manager and uh no privilege escalation. Also, you can use the runtime settings like uh tmpfs or mount to store the data outside the container. You can prevent the privilege escalation at runtime by using the security opt no new privileges option. You can also use the readonly flag to run the container with the readonly file system if it fits your use case. Aim for deterministic container images. Deterministic means that given the same input, the build produces the exact same bites. This way you can detect tempering or dependency change between the build runs. Pin everything to achieve determinism tool chain build system OS version. Also pin the base image by digest not by tag because tags can drift. But the digest always points to the image that you used in the first place.

Use SBOMs. A software bill of materials or an SBOM gives you a list of what's inside your image. Direct and indirect dependencies, their versions, licenses, and so on. SBOMS accelerate CV remediation because you can match a new CVE to the affected image. Generate an SBOMB with every image and store it alongside the image digest. There are several open-source tools for generating sbombs. For instance, sift or cyclonx generator. You can generate an SBOM at the pre-built stage to check the dependency state. But generating an sbomb at the build stage is a must because this way you get the list of exactly what you ship and run.

Integrate provenence. Provenence proves where this image came from by providing the metadata about where, when, and how this image was built. It is metadata that software consumers can verify independently of uh software producers. The important part of provenence is software attestation. You can use cosign for that. So you sign the artifact and the software consumer then verifies the signature and the required station in their CI/CD. Other provenence processes and tools are described in the supply chain levels for software artifacts framework or salsa for short. Drop me a comment if you want a separate video on that. Kow do-it-yourself base images. Quite a few teams build their images on some random base which can be poorly maintained, infected with CVS, lacking SBOMs, and just inviting malicious actors. So opt for a well-maintained regularly updated base image from a trusted vendor. The images should come with an SBOMB and should be easily verified by the check samp for instance instead of uh Alpine Linux with only the community support. You can use alpakita Linux with LTS releases and SLA for patches from bellsoft. Use LTS versions if possible. Consider using base images with LTS software versions. LTS releases are supported for several years. Plus, they have clearly defined security updates policies. For instance, NOJS LTS versions are released every year and receive security patches and critical fixes for 2 and 1/2 years. Java LTS versions are released every 2 years. And the support period depends on the JDK vendor. It varies from 3 years to more than seven years. As for the operating systems, Ubuntu LTS versions are released every two years and receive security patches for 5 years. Alpaquita LTS versions come out every 2 years and receive security patches for 4 years. Update base image regularly. If you don't update the base image, you accumulate nonvulnerabilities and extend the attack surface. Reliable vendors update their images constantly. But when a vendor releases an updated version of their image, your builds won't be updated automatically. So set up automatic uh updates monitoring using tools like dependabot and renovate. This way you can promptly rebuild, rescan and resign the container image.

No secrets in containers. Secrets baked into the image are a serious security risk. Use a dedicated secrets management tools like hash corp worlds, Google secrets manager or kubernetes secrets. You can store your secrets there and then patch them at runtime. Use security scanners. Security scanners are tools that analyze the software environments for security flaws. Scanners vary in purpose. They can scan dependencies, configs, sbombs, container images. They can search for CVS, secrecy, and configs. They can scan the source code for security weaknesses or even monitor the malicious activity. So you can use them at different stages of software development life cycle. You should also define policies for acting upon the scanning results. For instance, you can block or allow the build or deploy, create an additional artifact, perform a manual review and so on. Implement host hardening. Containers share the host kernel. So if the host is vulnerable, everything on it is vulnerable. You can use a dedicated OS for Kubernetes nodes such as Bottle Rock or a minimalistic OS such as Alpakita LTS. The key is that the system must be immutable and without any unnecessary components. Update the kernel on a regular basis plus enable Linux security modules to set the required security policies. Okay, I know this whole info may seem overwhelming. So, if you want to learn more about these approaches, I have written a dedicated article with a more detailed description of each approach and code samples. The link is in the description.

 

Summary

This video shows how to build a complete UI for a Spring Boot application using Vaadin, a Java web framework that provides rich, customizable UI components entirely in Java. The guide walks through creating a login page, a main layout with navigation, and a data grid that supports filtering, lazy loading, and detailed dialogs. It also demonstrates how to build a multi-tab dialog with read-only details and an admin-only edit form using Vaadin Binder for validation and data binding. The video explains how to integrate Spring Security, handle database data from MongoDB, and build responsive layouts. Finally, it shows how to apply a custom cyberpunk theme and encourages exploring Vaadin’s broader capabilities.

About Catherine

Java developer passionate about Spring Boot. Writer. Developer Advocate at BellSoft

Social Media

Videos
card image
Dec 12, 2025
Will AI Replace Developers? A Vibe Coding Reality Check 2025

Can AI replace software engineers? ChatGPT, Copilot, and LLM-powered vibe coding tools promise to automate development—but after testing them against 17 years of production experience, the answer is more nuanced than the hype suggests. Full project generation produces over-engineered code that's hard to refactor. AI assistants excel at boilerplate but fail at business logic. MCP servers solve hallucination problems but create context overload. Meanwhile, DevOps automation actually works. This breakdown separates AI capabilities from marketing promises—essential for teams integrating LLMs and copilots without compromising code quality or architectural decisions.

Videos
card image
Dec 12, 2025
JRush | Container Essentials: Fast Builds, Secure Images, Zero Vulnerabilities

Web-conference for Java developers focused on hands-on strategies for building high-performance containers, eliminating CVEs, and detecting security issues before production.

Further watching

Videos
card image
Dec 30, 2025
Java in 2025: LTS Release, AI on JVM, Framework Modernization

Java in 2025 isn't about headline features, it's about how production systems changed under the hood. While release notes focus on individual JEPs, the real story is how the platform, frameworks, and tooling evolved to improve stability, performance, and long-term maintainability. In this video, we look at Java from a production perspective. What does Java 25 LTS mean for teams planning to upgrade? How are memory efficiency, startup time, and observability getting better? Why do changes like Scoped Values and AOT optimizations matter beyond benchmarks? We also cover the broader ecosystem: Spring Boot 4 and Framework 7, AI on the JVM with Spring AI and LangChain4j, Kotlin's growing role in backend systems, and tooling updates that make upgrades easier. Finally, we touch on container hardening and why runtime and supply-chain decisions matter just as much as language features.

Videos
card image
Dec 24, 2025
I Solved Advent of Code 2025 in Kotlin: Here's How It Went

Every year, Advent of Code spawns thousands of solutions — but few engineers step back to see the bigger picture. This is a complete walkthrough of all 12 days from 2025, focused on engineering patterns rather than puzzle statements. We cover scalable techniques: interval math without brute force, dynamic programming, graph algorithms (JGraphT), geometry with Java AWT Polygon, and optimization problems that need constraint solvers like ojAlgo. You'll see how Java and Kotlin handle real constraints, how visualizations validate assumptions, and when to reach for libraries instead of writing everything from scratch. If you love puzzles, programming—or both—and maybe want to learn how to solve them on the JVM, this is for you.

Videos
card image
Dec 18, 2025
Java 26 Preview: New JEPs and What They Mean for You

Java 26 is the next feature release that brings features for enhanced performance, security, and developer experience. This video discusses the upcoming JDK 26 release, highlighting ten JEPs including JEP 500. JEP 500 focuses on preparing developers for future restrictions on mutating final fields in Java, emphasizing their role in maintaining immutable state. This is crucial for robust programming and understanding the nuances of mutable vs immutable data, especially concerning an immutable class in java. We also touch upon the broader implications for functional programming in Java.