{"id":18274065,"url":"https://github.com/iamriteshkoushik/container-from-scratch","last_synced_at":"2025-04-09T03:41:59.166Z","repository":{"id":277605793,"uuid":"880965669","full_name":"IAmRiteshKoushik/container-from-scratch","owner":"IAmRiteshKoushik","description":"Learning about containers and isolated environments. Try to build one from scratch using tutorials by Liz.","archived":false,"fork":false,"pushed_at":"2024-10-31T18:33:55.000Z","size":3284,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-14T22:17:24.895Z","etag":null,"topics":["cgroups","chroot","containers","namespace"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/IAmRiteshKoushik.png","metadata":{},"created_at":"2024-10-30T17:17:33.000Z","updated_at":"2025-01-23T09:15:26.000Z","dependencies_parsed_at":null,"dependency_job_id":"056ade62-32f0-4a1b-8627-9d4fc4d40dc5","html_url":"https://github.com/IAmRiteshKoushik/container-from-scratch","commit_stats":null,"previous_names":["iamriteshkoushik/container-from-scratch"],"tags_count":null,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IAmRiteshKoushik%2Fcontainer-from-scratch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IAmRiteshKoushik%2Fcontainer-from-scratch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IAmRiteshKoushik%2Fcontainer-from-scratch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/IAmRiteshKoushik%2Fcontainer-from-scratch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/IAmRiteshKoushik","download_url":"https://codeload.github.com/IAmRiteshKoushik/container-from-scratch/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247974595,"owners_count":21026742,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cgroups","chroot","containers","namespace"],"created_at":"2024-11-05T12:08:30.175Z","updated_at":"2025-04-09T03:41:59.161Z","avatar_url":"https://github.com/IAmRiteshKoushik.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Build your own container in Go\n\n\u003e [!WARNING]\n\u003e This repository must be cloned and run in Linux / Unix environments only. It \nis not built for windows.\n\n1. Namespaces\n2. Chroot (changing the root)\n3. Cgroups (control groups)\n\nWhen you run a container using docker - `docker run --rm -it ubuntu /bin/bash`\nThis runs the container and then removes it once the work is done. It is by \ndefault executing the bash shell \n\n## Namespaces\nLimit what a process can see. Created using `syscalls`\n- Unix Timesharing System\n- Process IDs\n- Mounts\n- Network\n- User IDs\n- InterProcess Comms\n\nThis plays a major role in restricting / isolating a container.\n\nAfter having created a separate and isolated process\n\nWhile creating a new namespace using `syscall.CLONE_NEWNS`, I have added the \n`Unshareflags: syscall.CLONE_NEWNS` which allows me to keep the data of the \nnamespace hidden. Things that are mounted inside the containerized environment\nwill not be visible to the host.\n  \nA before-after example of `mount | grep proc`\n```bash\n# before (observe the last line)\nproc on /proc type proc (rw,nosuid,nodev,noexec,relatime)\nsystemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=39,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=6362)\nbinfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,nosuid,nodev,noexec,relatime)\nproc on /home/rk/ubuntu-fs/proc type proc (rw,relatime)\n\n# after (the last line disappeared which is the relevant mount)\nproc on /proc type proc (rw,nosuid,nodev,noexec,relatime)\nsystemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=39,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=6362)\nbinfmt_misc on /proc/sys/fs/binfmt_misc type binfmt_misc (rw,nosuid,nodev,noexec,relatime)\n```\n\nYou can still look it up by putting the process to sleep and then using the pid\n```bash\nsudo cat /proc/\u003cpid\u003e/mounts\n```\n\n## Chroot (change root)\nThe chroot command can be used to setup and run programs or interactive shells \nsuch as Bash in an encapsulated filesystem that is prevented from interacting \nwith your regular filesystem. Everything within the chroot environment is penned \nin and contained. Nothing in the chroot environment can see out past its own, \nspecial root directory.\n\nLearn how to create a chroot directory here - [link](https://www.howtogeek.com/441534/how-to-use-the-chroot-command-on-linux/)  \nName this a `ubuntu-fs` and to run it in the code. The new container getting \ncreated will use this as the root point. This need not be the actual ubuntu \nfilesystem unless and until you are running on ubuntu.\n\n\u003e [!NOTE]\n\u003e `chroot` creation is at times, OS dependent and corresponding OS friendly \n\u003e guides are available on the internet. Personally, the above link did not \n\u003e workout for me as I am using Arch but for an Ubuntu user it would work just \n\u003e fine.\n\nAlternative is to get a filesystem and chroot into it programatically.\n```bash\n# Here, I am taking a redis docker container and extracting out the entire \n# filesystem to chroot into it. Ultimately it is a linux filesystem and all the \n# basic commands work. While it is not completely isolated and the host can \n# still access it, a certain level of permission setup should do the trick.\ndocker export $(docker create ubuntu) -o ubuntu.tar.gz\nmkdir ubuntu-fs \u0026\u0026 cd ubuntu-fs\ntar --no-same-owner --no-same-permissions --owner=0 --group=0 -mxf ../ubuntu.tar.gz\n```\n\nAnother alternative suggested by a friend is to use `debootstrap` program. It \ncreates a debian environment inside a sub-directory and lets you access it.\n\n## Cgroups (control groups)\n\nThis tells you what you can \"use\". Things like the filesystem interface\n- Memory\n- CPU\n- I/O\n- Process numbers\n\nThe way control groups are accessed also differs from OS to OS. \n\nIn the program, the we have setup a simple control group which controls the \nnumber of processes than can be run inside the container.\n\n```bash\n# The code limits the processes to be 20 in count, so in-order to test that \n:(){ :|: \u0026 };:\n```\n\nThis particular sketchy looking command starts forking the existing process on \na linux terminal. When that happens the max limit of 20 processes comes into play \nand blocks further forking. This is basically a fork-bomb.\n\n\u003e [!INFO] \n\u003e Tampering with control groups is fairly tricky. Be careful and figure out ways \n\u003e to remove control-groups after your job is done.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiamriteshkoushik%2Fcontainer-from-scratch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiamriteshkoushik%2Fcontainer-from-scratch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiamriteshkoushik%2Fcontainer-from-scratch/lists"}