Note: I am not a Container anatomy specialist or a Linux expert. This is my experiment with containers in order to understand them.
I am on a learning path to understand how containers work internally. Well, the answer is Namespaces, Cgroups, chroot and of course a filesystem.
Namespaces
Linux namespaces are a feature of the Linux kernel that allows the isolation and virtualisation of system resources between different processes. This means that processes within different namespaces can have their own independent view of the system's resources, such as process IDs, network interfaces, file systems, and other system resources
Cgroups
Cgroups are a fundamental technology in Linux containerization, allowing the isolation and management of resources among containers. For example, when a Docker container is created, it is assigned its own cgroup, and resources are allocated according to the limits set by the container configuration.
Chroot
chroot is a Unix and Linux system call and command-line tool that changes the root directory of a running process and its children to a new location in the filesystem. This effectively creates an isolated filesystem environment for that process, separate from the main filesystem hierarchy.
So basically Containers are chroot on steroids
Let's try creating our own.
- Create Namespaces:
unshare --uts --pid --net --mount --ipc --fork
- Setup Cgroups:
mkdir /sys/fs/cgroup/Example/
echo "200000 1000000" > /sys/fs/cgroup/Example/tasks/cpu.max
echo "$$" > /sys/fs/cgroup/Example/tasks/cgroup.procs
First line creates a new cgroup, second one assigns cpu quota
Third line attaches current shell to the cgroup of container
- Setup container's root filesystem:
debootstrap focal ./ubuntu-rootfs http://archive.ubuntu.com/ubuntu/
This installs a basic Debian or Ubuntu base system into a directory on an existing and running system.
- Mount and chroot into container's filesystem:
mount -t proc none ./ubuntu-rootfs/proc
mount -t sysfs none ./ubuntu-rootfs/sys
mount -o bind /dev ./ubuntu-rootfs/dev
chroot ./ubuntu-rootfs /bin/bash
These commands are used to set up a chroot environment, where you can operate within the directory ./ubuntu-rootfs as if it were the root of the filesystem. They mount various virtual filesystems and device files that a typical Linux system requires for normal operation. Here's what each command does:
-
mount -t proc none ./ubuntu-rootfs/proc-
mountis the command used to mount filesystems. -
-t procspecifies the type of filesystem to mount, which in this case isproc. Theprocfilesystem is a virtual filesystem that provides access to kernel and process information. -
noneis used here since theprocfilesystem does not correspond to a physical device. -
./ubuntu-rootfs/procis the directory where theprocfilesystem will be mounted. It is the/procdirectory within your chroot environment.
This command mounts the
procfilesystem into yourchrootenvironment, which is necessary for processes within the chroot to get information about the system and running processes. -
-
mount -t sysfs none ./ubuntu-rootfs/sys-
-t sysfsspecifies that thesysfsfilesystem type is to be mounted.sysfsis a virtual filesystem that provides a hierarchy of system and hardware information. -
noneis used here as well sincesysfsis also virtual. -
./ubuntu-rootfs/sysis the mount point within the chroot.
This command is similar to the previous but mounts the
sysfsfilesystem, which is necessary for interacting with system and hardware information. -
-
mount -o bind /dev ./ubuntu-rootfs/dev-
-o bindis an option to perform a bind mount. A bind mount creates a mirror of a directory or mount point to some other location. -
/devis the source directory that contains device nodes and interfaces that the kernel provides. -
./ubuntu-rootfs/devis the target directory where the device interfaces will be available within the chroot.
This command mounts the
/devdirectory into the chroot environment's/devdirectory, allowing access to the device files from within the chroot. Device files are needed, for example, to access hard drives, input devices, etc. -
-
chroot ./ubuntu-rootfs /bin/bash-
chrootchanges the root directory for the session, or for the command specified, to a new location. -
./ubuntu-rootfsis the new root directory where the chroot environment has been prepared. -
/bin/bashis the command to run in the chroot environment, in this case, the Bash shell.
This command enters the chroot environment. Once within the chroot, the user will be operating as if
./ubuntu-rootfswere the root (/) of the filesystem, and will start an interactive Bash shell. -
Well, we are done, you can run any commands that you want to run as we are now inside the "Container" and the environment is entirely isolated and processes inside it don't interact with the processes outside chroot
To get out of chroot, just press Ctrl + d and you will be out of it
References
- https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_monitoring_and_updating_the_kernel/using-cgroups-v2-to-control-distribution-of-cpu-time-for-applications_managing-monitoring-and-updating-the-kernel#preparing-the-cgroup-for-distribution-of-cpu-time_using-cgroups-v2-to-control-distribution-of-cpu-time-for-applications
- https://akashrajpurohit.com/blog/build-your-own-docker-with-linux-namespaces-cgroups-and-chroot-handson-guide/
- The series by DataDog --> https://securitylabs.datadoghq.com/articles/container-security-fundamentals-part-1/ https://securitylabs.datadoghq.com/articles/container-security-fundamentals-part-2/ https://securitylabs.datadoghq.com/articles/container-security-fundamentals-part-3/ https://securitylabs.datadoghq.com/articles/container-security-fundamentals-part-4/
Top comments (0)