Create "Container" without Docker
Tags: containers, cgroups, namespaces, linux
Published: 2024-03-19 16:59:06

**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:

1. **`mount -t proc none ./ubuntu-rootfs/proc`**
    - `mount` is the command used to mount filesystems.
    - `-t proc` specifies the type of filesystem to mount, which in this case is `proc`. The `proc` filesystem is a virtual filesystem that provides access to kernel and process information.
    - `none` is used here since the `proc` filesystem does not correspond to a physical device.
    - `./ubuntu-rootfs/proc` is the directory where the `proc` filesystem will be mounted. It is the `/proc` directory within your chroot environment.

    This command mounts the `proc` filesystem into your `chroot` environment, which is necessary for processes within the chroot to get information about the system and running processes.

2. **`mount -t sysfs none ./ubuntu-rootfs/sys`**
    - `-t sysfs` specifies that the `sysfs` filesystem type is to be mounted. `sysfs` is a virtual filesystem that provides a hierarchy of system and hardware information.
    - `none` is used here as well since `sysfs` is also virtual.
    - `./ubuntu-rootfs/sys` is the mount point within the chroot.

    This command is similar to the previous but mounts the `sysfs` filesystem, which is necessary for interacting with system and hardware information.

3. **`mount -o bind /dev ./ubuntu-rootfs/dev`**
    - `-o bind` is an option to perform a bind mount. A bind mount creates a mirror of a directory or mount point to some other location.
    - `/dev` is the source directory that contains device nodes and interfaces that the kernel provides.
    - `./ubuntu-rootfs/dev` is the target directory where the device interfaces will be available within the chroot.

    This command mounts the `/dev` directory into the chroot environment's `/dev` directory, allowing access to the device files from within the chroot. Device files are needed, for example, to access hard drives, input devices, etc.

4. **`chroot ./ubuntu-rootfs /bin/bash`**
    - `chroot` changes the root directory for the session, or for the command specified, to a new location.
    - `./ubuntu-rootfs` is the new root directory where the chroot environment has been prepared.
    - `/bin/bash` is 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-rootfs` were 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/