Container Image Security: Building Beyond Basic Deployment Strategies

Discover how to build secure, high-quality container images that go beyond basic functionality, focusing on best practices for robust application deployment.

Building 'Well-made' Container Images: Why It Matters Beyond Just Running

Hello, and welcome to your Aiden's Lab Notebook.

By now, container images are likely a concept you're quite familiar with in your own development projects. They guarantee a specific application will run in an isolated environment, making them almost essential if you're working with Kubernetes or public clouds like AWS, GCP, and others.

And because of this, you've probably found yourself building container images from scratch quite often. While you can certainly grab pre-built images from public repositories, there are those times when you just need to customize things to fit your project perfectly. You probably know what I mean.

So, when you're building that image, what's the first thing on your mind? For most of us, it's probably just getting the application to run successfully, right?

But is an image that just gets your application running 'well-made'?

The quality of container images goes beyond simply the ability for the application to run; it's also linked to the overall security and stability of the system, operational efficiency, and cost. High-quality container images form the basis for building a stable and efficient operating environment.

So, it becomes crucial to raise our awareness about container image quality and put in the effort right from the image build stage.

That said, the final quality of your container image is mostly determined by the image build process defined in your Dockerfile. Because…

  • Base image

  • Packages to install

  • Files to copy

  • User

Every single one of these elements is decided during the image build process.

This means that if you want your images to run safely and efficiently in production, it's absolutely essential to understand the process of writing your Dockerfile and building your image, and to actively work on optimizing it.

What Makes a Container Image 'Good' from a Security Perspective?

So what exactly is a well-made container image?

We can say a container image is well-made when it strikes a good balance between security and efficiency. Focusing specifically on the security side, the key requirements can be broadly summarized as follows:

  • Choosing the right base image

  • Removing unnecessary elements

  • Running with minimum privileges

Getting these two elements right – security and efficiency – is incredibly important in today's containerized environments.

That's why, in the rest of this post, I've put together some practical tips specifically focused on boosting security when you're building your container images. I've focused on practical, actionable steps you can apply right away, so definitely take a look!

Tips for Boosting Your Container Image Security

1. Selecting the Right Base Image for You (Alpine vs Distroless)

The base image is a really crucial piece, directly impacting both the final image's security and its size.

Minimal base images, in particular, include a severely limited set of operating system components, which effectively reduces both the image size and the security attack surface.

Among the most commonly used minimal base images are Alpine and Distroless.

  • Alpine:

    • Lightweight and easy package management.

    • It uses musl libc as its C library, which can lead to compatibility problems with applications using glibc. You might need to install extra packages to get things working.

  • Distroless:

    • Doesn't include a shell or basic tools, making it more secure and even lighter than Alpine.

    • However, because there's no shell, it can be challenging to debug after the container is running.

Since each option has its own distinct strengths and weaknesses, you'll need to consider your application's dependencies, whether you need certain tools readily available, and the specifics of your operating environment to pick the base image that fits best for you.

2. Removing Unnecessary Stuff in Your Image Using the RUN Instruction in Your Dockerfile

Cleaning up unnecessary files or caches left over from the build process can significantly reduce the security attack surface of your container.

Once you've installed all the packages you need using a RUN instruction in your Dockerfile, try adding a separate command like apt-get clean or other commands to remove cache files. This helps you get rid of data that's not needed for your application to run but could potentially be exploited in a security incident.

This approach also helps a lot with reducing the final image size.

3. Running the Container as a Non-Root User

If the processes running inside your container default to root privileges, the risk during a security incident becomes much higher.

By setting your application to run as a non-root user, you minimize the privileges an attacker would gain if unauthorized access occurs. This helps prevent damage from spreading to the host or other containers – think of it as limiting the 'blast radius'.

You can configure the commands within your image to run with limited privileges by using the RUN instruction to create a non-root user in your Dockerfile, and then specifying that user with the USER instruction. To make this a bit clearer, here's an example Dockerfile snippet:

# Create a new user (customuser) with UID 1234 and GID 1234
RUN groupadd -g 1234 customgroup && useradd -m -u 1234 -g customgroup customuser

# Change the user for this image to customuser
USER customuser

4. Excluding Sensitive Information During Image Build

It's incredibly dangerous to include sensitive information like database passwords, API keys, or cloud credentials directly within your image during the build process.

If you use ADD or COPY to include files containing sensitive info, or pass sensitive values via --build-arg, that data gets baked into your image layers and can be easily exposed.

Instead, sensitive information should always be injected securely at container runtime, not during the image build itself.

5. Using Container Image Security Tools

Using container image security tools like Trivy or Clair is a great way to check for security vulnerabilities in the images you build or plan to use.

  • Trivy:

    • An open-source vulnerability scanner that's fast and easy to use, scanning various targets including container images, file systems, and Git repositories.

    • It can scan not only OS packages but also application dependencies.

    • By integrating a Trivy scanning stage into your CI/CD pipeline, it can act as a 'security gateway,' preventing images with vulnerabilities from making their way into production.

  • Clair:

    • An open-source tool that analyzes container image components and reports vulnerabilities.

    • It supports periodically updating its vulnerability data and can send notifications via Webhooks.

    • Like Trivy, you can integrate it into your CI/CD pipeline to scan container images before deployment. You can also leverage its notification features (like Webhooks) to share scan results with your team.

Wrapping Up

Container images aren't really a 'set it and forget it' thing in the development process; they definitely require ongoing management.

New security vulnerabilities are constantly being discovered, and the base images and application dependencies your container image relies on also need regular updates.

As time goes on, both the security posture and the overall optimization of your container images are likely to degrade.

That's why, to keep your container images stable and up-to-date, you need a continuous rebuild process that includes regular vulnerability scanning and updates to your base image and dependencies.

But trying to do all of this manually can be quite challenging.

This is where leveraging a CI/CD pipeline comes in. Automating container image builds and uploads ensures efficiency and repeatability.

And as we touched on earlier, integrating the automatic security scanning features of tools like Trivy or Clair into this pipeline is a huge help in catching potential issues hidden within the image early on.

So, if you're using container images in your current projects, why not take a moment to look and see if there are areas where you can boost their security?

Since security is such a hot topic in the tech industry right now, it's not only a chance to broaden your own perspective on security but could also be a great opportunity to contribute to your team!

✨Enjoyed this issue?

How about this newsletter? I’d love to hear your thought about this issue in the below form!

👉 Feedback Form

Your input will be help improve Aiden’s Lab Notebook and make it more useful for you.

Thanks again for reading this notebook from Aiden’s Lab :)

References