How to make container from scratch
If you want to learn behind the scene about containers you are in the right place.
Firstly, you need to know your materials to create a container. Generally, users thought containers as lightweight virtual machines, but containers are isolated groups of processes running on a single host. That isolation can be creatable with underlying Technologies built into the Linux kernel: namespaces, cgroups, chroot, etc.
“Everything is a File” in Linux.
Before going into the syscalls you need to create a tiny file system first. Create simple docker image that is mentioned previous article [link..]
Then export the file system of that img with;
Command line argument -> $ sudo docker export “img name or img ID” > rootfs.tar.gz
here we are done:
The tools that we use;
Chroot, run command or interactive shell with special root directory.
Unshare, run program with some namespaces unshared from parent.
Nsenter, run program with namespaces of other processes.
Mount, mount a filesystem.
Cgroup, control group based traffic control filter.
Chroot allows us to restrict a process view of the file system. In this example we’ll restrict our process to the “rootfs” directory then exec a Shell.
Creating namespaces with unshare
Now we need to isolate our chrooted process. Run the “top” in another terminal. We can see the top command from the chrooted process.
Now we need namespaces to create restricted views of systems.
With the unshare command we can’t see the host’s processes anymore.
Getting around chroot with mounts
When deploying an “immutable” container it often becomes important to inject files or directories into the chroot, either for storage or configuration. For this example, we’ll create some files on the host, then expose them read-only to the chrooted shell using mount.
First, make a new directory to mount into the chroot and create a file there.
Command line argument ->$ ‘sudo mkdir readonlyfiles’ and ‘echo “hello” > readonlyfiles/hi.txt’
Next, we’ll create a target directory in our container and bind mount the directory providing the -o ro argument to make it read-only.
Command line argument -> $ ‘sudo mkdir -p rootfs/var/readonlyfiles’
Command line argument -> $ ‘sudo mount –bind -o ro $PWD/readonlyfiles $PWD/rootfs/var/readonlyfiles’
The chrooted process can now see the mounted files.
But, it cannot write there.
cgroups, short for control groups, allow kernel imposed isolation on resources like memory and CPU. We’ll create a cgroup to restrict the memory of a process. Creating a cgroup is easy, just create a directory. In this case, we’ll create a memory group called “demo”. Once created, the kernel fills the directory with files that can be used to configure the cgroup.
Let’s limit the cgroup to 100MB of memory and turn off swap.
The tasks file is special, it contains the list of processes which are assigned to the cgroup. To join the cgroup we can write our own PID.
cgroups can’t be removed until every process in the tasks file has exited or been reassigned to another group. Exit the shell and remove the directory with rmdir (don’t use rm -r).
This example, not a fully functional container. Just basic concept implemented with syscalls. I hope this is a good starting point for understanding lower level container technology.