Introduction
Containerization has revolutionized how we develop, deploy, and manage applications, with Docker being one of the most popular tools in the space. However, containers are not dependent on Docker; they are a feature of the Linux kernel. In this blog, well explore how to create a container manually in Linux without using Docker. Understanding the underlying mechanisms gives you a deeper appreciation for how containers work and offers flexibility in environments where Docker is not available or suitable.
Prerequisites
Before we begin, ensure you have a Linux system with root
or sudo
privileges. Additionally, you should have a basic understanding of Linux namespaces, control groups (cgroups), and chroot.
Key Concepts
Namespaces
Namespaces isolate the container's environment from the host system. The key namespaces well use are:
UTS namespace : Isolates hostname and domain name.
PID namespace : Isolates process IDs.
Network namespace : Isolates network interfaces.
Mount namespace : Isolates filesystem mounts.
User namespace : Isolates user and group IDs.
Control Groups (cgroups)
Cgroups limit and prioritize resource usage (CPU, memory, disk I/O) for a collection of processes. This ensures that your container doesnt consume more resources than allocated.
Chroot
Chroot changes the apparent root directory for a process, providing filesystem isolation.
Step-by-Step Guide to Creating a Container Manually
Step 1: Create a Root Filesystem
First, create a root filesystem for the container. You can use debootstrap
(Debian-based systems) or yum
/dnf
(Red Hat-based systems) to set up a minimal Linux environment.
mkdir /containerdebootstrap --arch=amd64 focal /container http://archive.ubuntu.com/ubuntu/
This command sets up an Ubuntu Focal Fossa environment in the /container
directory.
Step 2: Set Up Namespaces
We will use the unshare
command to create and isolate namespaces. The following command isolates UTS, PID, network, and mount namespaces:
unshare --fork --pid --mount --net --uts /bin/bash
You are now inside a shell with isolated namespaces.
Step 3: Configure the Filesystem with Chroot
Next, use chroot
to change the root directory to the new filesystem we created:
chroot /container /bin/bash
This command changes the root to /container
and spawns a new Bash shell. You are now inside an isolated filesystem.
Step 4: Set Up the Hostname and Networking
Set a hostname for your container:
hostname container-1
To configure networking, you can either set up a virtual network interface using tools like ip
or brctl
or manually add entries to /etc/hosts
and /etc/resolv.conf
.
Step 5: Apply Resource Limits Using Cgroups
Create a cgroup for your container:
mkdir -p /sys/fs/cgroup/cpu/containerecho 50000 > /sys/fs/cgroup/cpu/container/cpu.cfs_quota_usecho $$ > /sys/fs/cgroup/cpu/container/tasks
This limits the containers CPU usage to 50%. You can similarly manage memory, I/O, and other resources.
Step 6: Start and Manage Processes in the Container
rom the isolated environment, you can now run processes that are separate from the host system:
/bin/bash
Any process you start here will be contained within the namespaces and cgroups youve set up.
Step 7: Clean Up
When done, exit the chroot environment and the namespaces:
exit
Unmount filesystems, delete cgroups, and clean up resources to ensure no leftover configurations.
Conclusion
Creating a container manually without Docker involves isolating the environment using Linux namespaces, restricting resources with cgroups, and isolating the filesystem using chroot. While Docker simplifies these steps, understanding how to create containers manually provides insight into the inner workings of containerization, allowing for more customized and granular control when needed.
This hands-on approach is valuable for those who want to delve deeper into Linux systems, develop custom container solutions, or work in environments where Docker is not viable.
Top comments (0)