Uncover hidden risks

Watch how the Wiz platform can expose unseen risks in your cloud environment without drowning your team in alerts.

Linux containers: A security review

Understanding the nuances of Linux containers is crucial for building robust, secure applications. This blog post provides insights into the practical implementation of containers, focusing on both their strengths and potential pitfalls.

7 minutes read

Linux containers are compact, self-sufficient software units that bundle application containers with source code, language bindings, runtime, system tools, environment variables, and configurations. This packaging guarantees that applications operate swiftly and dependably across various computing environments.

In contrast to conventional virtual machines, which contain entire operating system images, containers utilize the kernel of the host operating systems and run in separate user spaces, offering more efficient deployment.

Understanding the nuances of Linux containers is crucial for building robust, secure applications. This blog post provides insights into the practical implementation of containers, focusing on both their strengths and potential pitfalls. Whether you’re considering unprivileged containers for added security or managing a container pipeline for continuous integration and deployment, grasping these concepts empowers developers to make the most of the containerized deployment of applications.

Understanding Linux containers

A brief history of Linux containers

Linus Torvalds first began developing Linux in 1991. In 2001, the introduction of the chroot mechanism in UNIX-like systems created isolated file environments, which jump-started the evolution of Linux containers. OpenVZ followed in 2005, providing isolated environments called virtual environments (VEs) that shared the Linux kernel. In 2008, Linux Containers (LXC) emerged, integrating cgroups and namespaces for flexible containerization. 

Docker revolutionized Linux containers in 2013 by simplifying container creation and management, and Docker containers gained popularity for their ease of use and CI/CD integration. (Docker is commonly thought of as the source project for container technologies, even though it emerged long after the first implementations of containers.) Today, the container ecosystem includes a variety of tools like Kubernetes for container orchestration, along with various container managers and container runtimes such as CRI-O and containerd.

Key technologies behind containers

The key technologies that make Linux containers possible are cgroups, namespaces, and various kernel features. These technologies enable containers to run in isolation from each other while sharing the same kernel, offering efficiency and security:

  • Namespaces: Namespaces provide the foundation for container isolation. Each namespace type isolates different parts of the system, including process IDs (PID namespaces), network interfaces (network namespaces), and user IDs (user namespaces). This separation ensures that processes within a container cannot see or affect those outside it.

  • cgroups: Control groups (cgroups) manage and limit the resources that a container can consume. By setting resource limits on CPU, memory, and I/O, cgroups prevent a single container from monopolizing the host machine's resources, thus maintaining overall system stability and performance.

  • Seccomp and AppArmor: These security features enhance container security by restricting the system calls containers can make and confining containers to specific security profiles, respectively.

Comparing containers with virtual machines (VMs)

The primary differences between containers and VMs lie in their architecture and resource utilization. These differences have significant implications for both security and efficiency:

ArchitectureShare the host OS kernel and run in isolated user spacesEach VM includes a full OS with its own kernel
Resource utilizationLightweight, lower resource consumptionHeavier, higher resource consumption due to multiple OS instances
Startup timeFast startup (seconds)Slower startup (minutes) due to full OS boot process
IsolationProcess and file system isolationStronger isolation with separate kernels
PerformanceNear-native performance, efficient use of resourcesIncreased overhead due to virtualization layer
SecurityShared kernel can be a security risk if compromisedStronger isolation as each VM runs on a separate kernel
Use casesMicroservices, cloud-native applications, CI/CD pipelinesLegacy applications, multi-OS requirements, heavy container workloads

Understanding these differences helps you make informed decisions about when to use containers versus VMs, particularly when security and resource efficiency are critical.

Security advantages of Linux containers

  • Isolated execution environment: One of the critical security benefits of Linux containers is the isolated execution environment they provide. Every container runs in a separate user space that separates the container from other containers and the host. This isolation limits the impact of any security breaches on the affected container, protecting the overall system.

  • Minimalist base images: Using minimalist base images is a best practice that reduces the attack surface of containers. Attackers can exploit fewer potential vulnerabilities by including only the essential components needed to run an application.

  • Immutability and ephemeral nature: Containers are intended to be immutable and short-lived. Once a container image is created, it does not change. If a container is compromised, it can be quickly replaced with a fresh instance from the original image, limiting the duration of an attack and facilitating rapid recovery.

Security challenges of Linux containers

  • Kernel exploits: While containers provide isolation, they share the host kernel. This shared dependency means that a vulnerability in the host kernel could potentially lead to container escapes and host compromise. Ensuring that the host kernel is secure and up-to-date is critical.

  • Configuration errors: Misconfigurations can expose sensitive information or unintentionally open network ports, leading to security breaches. It’s essential to follow best practices and use automated tools to detect and fix misconfigurations.

  • Networking and communication risks: Containers often require complex networking setups, which can introduce security risks if not properly managed. Misconfigured networks can lead to unauthorized data exposure and other vulnerabilities.

  • Supply chain risks: Container images frequently originate from unknown or public registries. Deploying containers based on public images poses security challenges because you can’t be confident about the integrity of the images—they might have been tampered with, introducing vulnerabilities into the environment. It's crucial to verify and secure the supply chain of container images.

Best practices for securing Linux containers

1. Use trusted base images

Using trusted base images minimizes the risk of vulnerabilities and ensures a secure foundation for your containers:

  • Always source pre-built container images from official or verified repositories.

  • Regularly update your container images with the latest security patches.

  • Use tools like Clair, Trivy, and services from cloud providers to scan for vulnerabilities in your images.

Here’s a Dockerfile example that uses an official base image:

FROM ubuntu:20.04
# Installing necessary packages
RUN apt-get update && apt-get install -y \
    curl \
    vim \
    && rm -rf /var/lib/apt/lists/*

2. Implement the least-privilege principle

Running containers with as few permissions as possible reduces the potential impact of a security breach:

  • Avoid running containers as root or using privileged containers unless absolutely necessary.

  • Define and enforce security contexts in Kubernetes manifests and limit container users.

  • Utilize unprivileged users to reduce risk further in production environments.

Use this sample code to create a Kubernetes pod with a non-root user who is in a precise range of UIDs specified in the security context:

apiVersion: v1
kind: Pod
  name: non-root-pod
  - name: app
    image: your-app-image:latest
      runAsUser: 1000
      runAsGroup: 3000
      fsGroup: 2000

3. Integrate security in the CI/CD pipeline

Incorporating security checks into your CI/CD pipeline ensures vulnerabilities are found and mitigated early in the development cycle:

  • Integrate security scanning tools like Trivy and Clair into your CI/CD pipelines before the deployment of containers.

  • Automate security policy enforcement using tools like OPA Gatekeeper.

  • Ensure all stages of the container life cycle include security checks.

This Jenkins pipeline example integrates security checks:

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                sh 'docker build -t your-app-image .'
        stage('Scan') {
            steps {
                sh 'trivy image your-app-image'
        stage('Deploy') {
            steps {
                sh 'docker-compose up -d'

4. Implement network security policies

Applying network security policies can control traffic between containers and restrict unauthorized access:

  • Define and enforce network policies to control traffic between pods and services.

  • Use Kubernetes network policies to restrict ingress and egress traffic based on labels.

  • Regularly review and update network policies to adapt to evolving security requirements.

Here’s an example Kubernetes network policy that restricts access between containers labeled as web, api, and database, specifically allowing ingress traffic from web to database and egress traffic from database to api on port 9090:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
  name: restrict-app-traffic
  namespace: default
      app: database
  - Ingress
  - Egress
  - from:
    - podSelector:
          app: web
  - to:
    - podSelector:
          app: api
    - protocol: TCP
      port: 9090

5. Implement runtime protection

Ensuring real-time monitoring and protection of your running containers is a crucial means of detecting and mitigating threats:

  • Use tools like Falco to monitor container activity and detect anomalies.

  • Implement runtime security policies to enforce expected behavior and block malicious activities.

  • Continuously monitor logs and events for signs of breaches or abnormal activities.

Here’s an example of setting up runtime security policies using Falco to monitor and alert on suspicious activities:

apiVersion: v1
kind: ConfigMap
  name: falco-config
  namespace: kube-system
  falco_rules.local.yaml: |
    - rule: Write below root
      desc: Detect any write below / (not allowed)
      condition: write and not fd.name in (user_files, proc_files)
      output: "Write below root detected (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline parent=%proc.pname file=%fd.name)"
      priority: ERROR

Wiz and container security

Wiz provides a comprehensive cloud security platform that seamlessly integrates into your development workflow to protect containerized environments from build-time to runtime. By leveraging direct connections to Kubernetes clusters and cloud-provider APIs, Wiz ensures continuous monitoring and real-time detection of vulnerabilities. 

The Wiz Security Graph offers a clear, context-driven insight into potential risks, helping teams prioritize and mitigate threats efficiently. With tools for vulnerability management, compliance, and infrastructure as code (IaC) scanning, Wiz enables developers to secure container ecosystems.

Request a demo today and take the first step towards a more resilient containerized environment.

What's running in your containers?

Learn why CISOs at the fastest growing companies use Wiz to uncover blind spots in their containerized environments.

Get a demo

Continue reading