top of page
  • Facebook
  • Twitter
  • Instagram
  • YouTube

Redefining the relationship between developers and containers

  • Writer: Taylor Etheredge
    Taylor Etheredge
  • 3 days ago
  • 4 min read

In the ever-evolving landscape of containerization, Podman has emerged as a powerful, daemonless alternative to Docker. By removing the daemon out of the scenario, developers can now more easily streamline their development process by not having to intervene with Docker's daemon, providing more reliability during runtime. This post aims to provide a way that hopefully helps bring a better understanding of what happens under the hood when you type "podman run"? The answer lies, in large part, with a lean container runtime called runC.


Podman is now the conductor of the containers, taking the place of Docker. It understands your commands and orchestrates the creation and management of containers. However, Podman itself doesn't directly interact with the Linux kernel to start the container. That's where runC comes into play, which runs its commands to translate that to the Linux Kernel. The outline presented below is a high-level overview with details on how Podman and runC interact between each other.


runC: The Engine Room of Containerization

runC is a lightweight, portable, and command-line tool for spawning and running containers according to the Open Container Initiative (OCI) specification. The OCI provides an open standard for container formats and runtimes, ensuring interoperability across different containerization tools. Podman, being apart of the OCI, relies on runC as its default runtime.


Fine tuned integration: Podman and runC in Action

Let's break down the process when you instruct Podman to run a container:

  1. Podman Receives Your Command: You issue a command like podman run -d nginx:latest. Podman parses this command, pulling the specified image (nginx:latest) if it's not already present locally.

  2. Generating the OCI Configuration: Podman then takes the image and your runtime options (like port mappings, volume mounts, etc.) and translates them into an OCI runtime configuration. This configuration is typically a config.json file that meticulously details how the container should be set up. It specifies things like:

    • The root filesystem for the container.

    • Resource limits (CPU, memory).

    • Namespaces to be created or joined.

    • Control Groups (cgroups) to be applied.

    • Security settings (SELinux labels, capabilities).

    • Mount points.

    • The command to be executed inside the container.

  3. Handing Off to runC: Once the OCI configuration is ready, Podman invokes the runC binary, passing it the path to the configuration and a unique ID for the container. The magic now begins!

  4. runC and the Linux Kernel: A Deep Dive

    This is where runC directly interacts with the Linux kernel to create the isolated container environment. It achieves this by leveraging several powerful Linux kernel features:

    • Namespaces: Namespaces provide the fundamental isolation for containers. runC uses various namespace types to create isolated views of system resources for the container:

      • PID Namespace: Isolates the process ID space, so the container has its own init process (PID 1) and doesn't see processes from the host or other containers.

      • Network Namespace: Provides an isolated network stack, allowing containers to have their own IP addresses, network interfaces, and routing tables.

      • Mount Namespace: Isolates the filesystem mount points, allowing containers to have their own root filesystem and different mount views.

      • UTS Namespace: Isolates the hostname and domain name.

      • IPC Namespace: Isolates inter-process communication (IPC) resources like message queues and shared memory segments.

      • User Namespace: Allows mapping user and group IDs inside the container to different IDs on the host, enhancing security by running processes inside the container as unprivileged users on the host.

    • Control Groups (cgroups): cgroups are a Linux kernel feature that allows for the limitation and accounting of resource usage (CPU, memory, I/O) for a group of processes. runC uses the cgroup configuration specified in the OCI config to enforce resource constraints on the container. This ensures that one container doesn't over take the system resources.

    • Security Features: runC also configures various security mechanisms provided by the Linux kernel:

      • Capabilities: These divide the traditional root privileges into distinct units. runC can drop unnecessary capabilities from the container process, reducing the attack surface.

      • SELinux/AppArmor: If enabled on the host, runC can apply SELinux or AppArmor profiles to the container, further restricting its access to system resources.

      • Seccomp: Secure Computing mode allows filtering of system calls that a process can make. runC can configure seccomp profiles to restrict the kernel system calls available to the containerized application, significantly enhancing security.

  5. Starting the Container Process: Once the namespaces, cgroups, and security settings are configured, runC executes the container's entrypoint command specified in the OCI configuration within this isolated environment.

  6. Podman Takes Over Management: After runC has successfully created and started the container process, it exits. Podman then takes over the ongoing management of the container, allowing you to interact with it through commands like podman ps, podman logs, and podman exec.


Working together fosters an essential degree of abstraction

The collaboration between Podman and runC provides a powerful yet user-friendly experience. Podman abstracts away the complexities of directly interacting with the Linux kernel, while runC efficiently and securely handles the low-level container creation and execution. This separation of concerns makes containerization accessible to a wider audience while still providing fine-grained control when needed.


In Conclusion

The next time you run a Podman container, those the intricate details happening behind the scenes, will no longer be a mystery. Podman orchestrates the process, generating the OCI specification, and then hands the process to the engine of runC. runC, in turn, integrates efficiently and effortlessly interfaces with the Linux kernel, leveraging namespaces, cgroups, and security features to create the isolated and resource-managed environments we know as containers. It showcases the power and flexibility of the Linux kernel, along with the creativity found in open-source containerization technologies.


 
 
 

Subscribe to Receive Our Latest Tech News

About the Author

A Network Automation Engineer that uses Python and it's packages to implement and scale networks.

© 2035 by tetheredge-time. Powered and secured by Wix

bottom of page