Linux Containers Internals: chroot Again
Intro to Linux Containers Internals:
In our last post of the series #lci-series, we scratched the surface of what
chroot does. It was great to get some feedback on how this lit some light bulbs. We can now agree on the definition that a container is a set of 1 or more processes isolated from the rest of the system. We saw this when we could isolate
bash just within our
container-intro directory. This was just one aspect of isolation - filesystem isolation.
By the way,
chrootwas introduced in Unix around 1979. That’s how old this concept is, and that marked the early beginnings of containers as we know them today. You can read more about the history here - A Brief History of Containers: From the 1970s Till Now.
In this series, we would like to explore
chroot further, this time with a full filesystem, as opposed to the hacky approach we used previously.
On your Linux system, start by installing
sudo apt install -y binutils debootstrap
Next, let’s create our directory for the root filesystem. If you are using WSL on Windows like me, make sure you are working from the linux filesystem and not the “Windows mount”, i.e.
/mnt/c/.... Therefore, you can
cd $HOME and work from there.
# assuming you are in $HOME sudo mkdir ubuntufs
debootstrap to create a Ubuntu 22.04 (
# jammy is the name for Ubuntu 22.04, see https://wiki.ubuntu.com/Releases sudo debootstrap --arch amd64 jammy ./ubuntufs http://archive.ubuntu.com/ubuntu # after running, the last lins should read something like: # ... # I: Base system installed successfully.
ℹ️ Note: another way of getting a filesystem without using
debootstrapis exporting a Docker container and then extracting it with
docker export $(docker create ubuntu) | tar -C rootfs -xvf -. However, we said we don’t want to use Docker for demystification.
chroot into the directory:
sudo chroot ubuntufs
And we are in:
root@nandaa-x1:/# ls bin boot dev etc home lib lib32 ...
ps to list processes, however, you will need to first mount
/procis a virtual filesystem, sometimes referred to as a process information pseudo-file system; that contains runtime system information (e.g. system memory, devices mounted, hardware configuration, etc). You can read more about it here.
root@nandaa-x1:/# ps Error, do this: mount -t proc proc /proc root@nandaa-x1:/# mount -t proc proc /proc root@nandaa-x1:/# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 1744 1080 ? Sl 15:27 0:00 /init root 7 0.0 0.0 1752 68 ? Ss 15:27 0:00 /init root 8 0.0 0.0 1752 76 ? S 15:27 0:00 /init 1000 9 0.0 0.0 6332 5368 ? Ss 15:27 0:00 -bash root 14351 0.0 0.0 8912 5564 ? R+ 15:55 0:00 sudo chroot co root 14352 0.0 0.0 8912 880 ? Ss 15:55 0:00 sudo chroot co root 14353 0.0 0.0 5040 4000 ? S 15:55 0:00 /bin/bash -i root 14365 0.0 0.0 1752 68 ? Ss 15:58 0:00 /init root 14366 0.0 0.0 1752 76 ? S 15:58 0:00 /init 1000 14367 0.0 0.0 6072 5180 ? Ss+ 15:58 0:00 -bash root 14380 0.0 0.0 7784 3300 ? R+ 15:58 0:00 ps aux
In a new tab, if you ran
ps aux on the main system, you should see a similar output. This is because we have not yet achieved namespace isolation, only filesystem isolation. We will cover namespace isolation in our next episode.
Thanks for reading this far; here is another small gift for you 🙂