{"id":24769622,"url":"https://github.com/sweetbbak/containers-for-dummies","last_synced_at":"2025-10-11T19:31:00.614Z","repository":{"id":198798395,"uuid":"701572759","full_name":"sweetbbak/Containers-for-dummies","owner":"sweetbbak","description":"Containers... What are they? How do they work? and how do I make one from scratch with absolutely no skills and 4 brain cells? We want containers in plain English dude... You came to the right place. ","archived":false,"fork":false,"pushed_at":"2023-10-07T20:20:51.000Z","size":286,"stargazers_count":11,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2023-10-08T01:27:11.940Z","etag":null,"topics":["blog","chroot","containerization","containers","isolation","tutorial"],"latest_commit_sha":null,"homepage":"","language":"Shell","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/sweetbbak.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-10-07T00:26:29.000Z","updated_at":"2023-10-08T01:14:10.000Z","dependencies_parsed_at":null,"dependency_job_id":"2507e313-c260-44ab-bb20-6704c1942cf2","html_url":"https://github.com/sweetbbak/Containers-for-dummies","commit_stats":null,"previous_names":["sweetbbak/containers-for-dummies"],"tags_count":0,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sweetbbak%2FContainers-for-dummies","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sweetbbak%2FContainers-for-dummies/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sweetbbak%2FContainers-for-dummies/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sweetbbak%2FContainers-for-dummies/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sweetbbak","download_url":"https://codeload.github.com/sweetbbak/Containers-for-dummies/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236122005,"owners_count":19098257,"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":["blog","chroot","containerization","containers","isolation","tutorial"],"created_at":"2025-01-29T03:00:45.377Z","updated_at":"2025-10-11T19:30:55.329Z","avatar_url":"https://github.com/sweetbbak.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Containers for dummies\n\n_Disclaimer_\nI am a dummy myself, this is how someone like myself understands\na concept that seems a lot more complex than it really is. Containers are awesome\nbut the current ecosystem around them is NOT simple whatsoever, and finding answers\nin plain English is next to impossible.\n\nSo, with my limited understanding, in programming and in containers...\nI will try my best to make a simple explanation so that anyone can get the\nbasic idea (including myself) I have less than a year of experience with Linux, programming\nand containers.\n\n---\n\n## **Containers**\n\n## Why a container?\n\nThe Magic Box: Think of a Linux container as a special box that you can put your toys (or programs) in. This box is like a mini-computer inside your computer.\n\nIsolation: Each box (container) is like its own little world. Inside, you can have one program, like a game, and it won't know or bother the other programs in their own boxes. It's like having separate rooms for your toys.\n\nSharing: Even though they're in separate boxes, containers can still talk to the outside world when they need to. They can share some things, like the internet or files, but only if you let them.\n\nEasy to Move: Containers are like toy boxes that you can easily pick up and move to different places, like to your friend's house or even to a big playground (which is a real computer server). This makes it easy to run the same program on different computers without any problems.\n\nConsistency: When you put the same toy in different containers, it's always the same toy. Similarly, when you put the same program in different containers, it behaves the same way, which helps keep things predictable and reliable.\n\nResource Control: You can also decide how much space, memory, and CPU power each container gets. It's like saying, \"This container can have a big play area, but that one only gets a small space.\"\n\nSo, Linux containers are like magical boxes that let you keep your programs separate, but still, let them play nicely together when you want. They make it easy to move your programs around and control how much of your computer's resources they use. It's like having a neat and organized way to play with all your favorite toys!\n\n---\n\n## What make's up a container?\n\nThe Root File System: Think of the root file system as a magic sandbox. It's like a small world where your toy programs will live. You start by making a special folder (sandbox) on your computer and put everything your toy program needs inside it. This includes all the toy parts and instructions (files and programs) that your toy needs to work.\n\nchroot Command: Now, you use a special command called chroot. It's like a magic spell that says, \"Hey, toy program, you can only see and play with the stuff inside this sandbox!\" You run this command to enter the sandbox, and now your toy program thinks it's in its own little world.\n\nProcess Isolation: Once inside the sandbox, your toy program can't see or touch anything outside of it. It's like putting a bubble around it so it doesn't mess up your room (your main computer). It can only play with the toys (files and programs) you put inside the sandbox.\n\nSo, you've created a container by making a special sandbox (root file system), using the chroot command to enter it, and then isolating your toy program so it can't affect anything outside the sandbox. This way, you can run different programs in their own sandboxes without them causing chaos in your room (computer).\n\n---\n\nContainers are deceptively simple things.\nGo ahead and run:\n\n```sh\n  ls /\n```\n\nwe should see something like this:\n\n![picture of root directory](images/root.png)\n\n```sh\nbin -\u003e usr/bin\nboot\ndev\nefi\netc\nhome\nlib -\u003e usr/lib\nlib64 -\u003e usr/lib\nlost+found\nmnt\nopt\nproc\nroot\nrun\nsbin -\u003e usr/bin\nsrv\nsys\ntmp\nusr\nvar\n```\n\nIt's essentially the common Linux filesystem. Most root directories are structured in a fairly similar way.\nWe can see some directories and a few symlinks to other directories for compatibility reasons.\n\n---\n\nin `/usr/bin` we see binaries that are often found on most Linux distributions. Like\nthe core utilities for example (ls, cat, less, head, sed, chroot, sudo) etc...\n\nPoking around in there and we see a lot of interesting things and locations where\nfiles are kept. Including libs in `/usr/lib` and boot files in `/boot` as well as some\nsymlinks to other directories for compatiblity and legacy reasons.\n\nFor the most part, this is what makes up the core of a Linux system (besides the Kernel)\n\n---\n\n## Creating our own Container.\n\nThe goal is replicating the root folder of a linux system, and isolating the filesystem and the\nnamespace that programs run in.\n\nFirst:\n\n- Pull an image from Docker hub (or a similar registry)\n  run the included image pull script that I got from github.com/moby/moby\n\n```sh\n  # ./download-frozen-image.sh \u003coutput-dir\u003e \u003cimage\u003e\n  ./download-frozen-image.sh arch-dir archlinux:latest\n```\n\nThis will downlaod the latest arch linux image from Docker hub.\nDocker hub has a lot of images that you can pull from and a lot of different\nrelease tags from the creators of the image. Like `archlinux:base-devel` or\n`debain:latest` etc...\n\nLets run `ls arch-dir` to see the contents of the directory that holds the information\nabout the image we just downloaded...\n\n![picture of the directory](images/dir.png)\n\n```\n51e4cf10935ead003f616f2363ae3260e28c7bc9536763dc0631638526168e2b\n879df13c861a38a80e992a4ef150d4a6527f62993cc6e79ab0141e7e42d30f4a\n2453f16847591dc207580fbab7ae626626f9d3ab347f7efd66eb2ee25c8969b7.json\nmanifest.json\nrepositories\n```\n\noof, that looks like shit. Whats with this gibberish?\nlets pick it apart one by one...\n\nlets look in the `manifest.json`\n\n```json\n[\n  {\n    \"Config\": \"2453f16847591dc207580fbab7ae626626f9d3ab347f7efd66eb2ee25c8969b7.json\",\n    \"RepoTags\": [\"archlinux:latest\"],\n    \"Layers\": [\n      \"879df13c861a38a80e992a4ef150d4a6527f62993cc6e79ab0141e7e42d30f4a/layer.tar\",\n      \"51e4cf10935ead003f616f2363ae3260e28c7bc9536763dc0631638526168e2b/layer.tar\"\n    ]\n  }\n]\n```\n\nOpening the `Config` field json we can see some basic information about the image...\nThe output is long but I will summarize it.\n\n- It contains an entry point command `/usr/bin/bash`\n- the $PATH variable, LC_ALL=C and other arch linux default environment variables.\n- Alongside some info about the maintainers, License, and things like that. As well as some history on the container.\n\nHey! We recognize those `RepoTags` thats what we used to pull this image.\nwhats really important to start things off is the Layers.\n\n---\n\n## **Layers**\n\nLets list the contents of the first layer.\n\n```sh\n  tar --list --file \"879df13c861a38a80e992a4ef150d4a6527f62993cc6e79ab0141e7e42d30f4a/layer.tar\n```\n\nIf we only look at the files at the top level we get:\n![](images/root.png)\n\nWow! It looks exactly like when we ran `ls /` earlier! That's because it is. (for the most part)\nthis is our base system layer! It contains all of the same system files that would be found on\nany normal Linux system after a fresh install.\n\nThe first layer is our base system layer.\n\n---\n\nLets look at the next layer\n\n```sh\n  tar --list --file 51e4cf10935ead003f616f2363ae3260e28c7bc9536763dc0631638526168e2b/layer.tar\n```\n\nHmm, its similar but only has a few files instead of the 100's of files that the base layer had.\n\n```\netc/\netc/ld.so.cache\netc/os-release\nvar/\nvar/cache/\nvar/cache/ldconfig/\nvar/cache/ldconfig/.wh..wh..opq\nvar/cache/ldconfig/aux-cache\n```\n\nthats because this is the next \"Layer\" that needs to be overlayed on to the base layer.\nThis layer is sort of like a \"diff\", meaning that instead of distributing the full system\nimage _plus_ these small changes to certain files, we just put the difference between\nthe layers into a new layer and distribute the changed files.\n\n---\n\n- example:\n  if I wanted to add a `/nix` folder in the root directory and distribute that as an image,\n  would I rather create a whole new tar archive that contains all of the base system files\n  with my changes included...\n\n- or would I just keep the base image as its own layer and create\n  a new layer that contains the `/nix` directory?\n\nObviously its the latter. It would be very\nineffecient space-wise to distribute every change as a full image file. So instead we `layer` all\nchanges. This provides a lot of layers of convenience. We can easily revert changes by removing a\nlayer, or make new changes by adding a new layer.\n\nTo finish the example, we could create a `layer.tar` that contains our `/nix` folder\n(You don't need to do this part, this is to better understand why layers are used)\n\n```\n  mkdir -p our_layer/nix\n  tar -cf our_layer/layer.tar our_layer/nix\n```\n\nand add our layer to the Json\n\n```json\n[\n  {\n    \"Config\": \"2453f16847591dc207580fbab7ae626626f9d3ab347f7efd66eb2ee25c8969b7.json\",\n    \"RepoTags\": [\"archlinux:latest\"],\n    \"Layers\": [\n      \"879df13c861a38a80e992a4ef150d4a6527f62993cc6e79ab0141e7e42d30f4a/layer.tar\",\n      \"51e4cf10935ead003f616f2363ae3260e28c7bc9536763dc0631638526168e2b/layer.tar\",\n      \"our_nix_folder_layer_would_go_here/layer.tar\"\n    ]\n  }\n]\n```\n\nNow we can easily use any combination of these layers as we need to. We can also easily add\nnew layers or revert back to the base layer if you want to undo changes. In its simplest form\nit is a form of `version control` with the idea of distributing the most minimal amount of data.\n\nDon't worry if this is a little dense, it'll make more sense once you see it happen... So lets do it.\n\n---\n\n## Creating a Container using Docker hub image metadata manually\n\nIts hard af to get a straight answer on creating a docker image manually, WITHOUT using Docker/Podman directly.\nIt's useless. We want to understand wtf is happening, and not rely on every little abstraction\nto carry us.\n\n- So here's how:\n\n(Please note that you can do this manually, or programatically - like pulling this info\ndirectly from Docker and parsing the layers and doing the following instructions)\n\nAlright lets freaking go already:\n\n- Create a temp directory\n\n```sh\n  mkdir my_pod\n```\n\n- Extract the base layer\n\n```sh\n  tar --extract --file 879df13c861a38a80e992a4ef150d4a6527f62993cc6e79ab0141e7e42d30f4a/layer.tar --directory=my_pod/\n```\n\nNow our \"base image\" is in our temp directory\n\n- Extract the other layers\n  the layers are in descending order, meaning we go through the `layers` field of our `manifest.json`\n  one at a time and extract each one into the `my_pod` temp directory that will serve as our new root\n  folder for our image\n\nthis tar command extracts `X` file into the specified `directory`\n\n```sh\n  tar --extract --file 51e4cf10935ead003f616f2363ae3260e28c7bc9536763dc0631638526168e2b/layer.tar --directory=my_pod/\n  # if we want to put our own layer on top of that we could do so with our own layer\n  tar --extract --file our_nix_folder_layer_would_go_here/layer.tar --directory=my_pod/\n```\n\ntar in this case is overwriting the files in the base image layer with the files in our newer layers.\nthis is so that we can apply our changes and revisions as described earlier.\n\nAt this point we essentially have 90% of a container.\nThe next to critical steps left are:\n\n- `Chroot`\n- and `Process isolation`\n\nfor now lets just worry about chroot. Lets just use the Unix coreutil util `chroot`\n\n---\n\n- Run:\n\n```sh\n  sudo chroot my_pod\n```\n\nand BOOM babyyy! you should see:\n\n```sh\n[root@sweetd /]#\n```\n\n---\n\nthe same thing in Go-lang would look like:\n\n```go\n  // .. ^ more stuff up here\n\t// now we chroot into the temporary directory\n\terr = syscall.Chroot(tempDir)\n\tif err != nil {\n\t\tfmt.Printf(\"Error chrooting: %v\\n\", err)\n\t\treturn err\n\t}\n\n// This function isolates the process by creating new namespaces\nfunc isolateProcess() error {\n\t// adding addtional namespace i.e., pid namespace, UTS namespace, mount namespace for more isolation\n\tif syscall.Unshare(syscall.CLONE_NEWUTS|syscall.CLONE_NEWPID|syscall.CLONE_NEWNS) != nil {\n\t\treturn fmt.Errorf(\"Error unsharing\")\n\t}\n\treturn nil\n}\n```\n\nIn this case we also create a new Namespace for the container so that the processes are isolated\nas well.\n\n---\n\n## Wrapping up\n\nIn the most simplest terms a `Container` is a directory that pretends to be a linux `/` root folder...\n\nThen, we ask the Linux Kernel:\n\"Hey, bro can you treat this folder as a `root` directory and give that baby a\nshiny new namespace/pid namespace/mount namespace to frolick and play in?\"\n\nand Linus Torvalds is personally like,\n\"Yea, dude. I got you fam. You are now chilling in a new root.\"\n\nWe have \"Changed root's\" so to speak... wait a minute Ch..ange root? Ch-root? CHROOT! CHROOT! CHROOT!\n\n---\n\nThis has been a lesson on containers from a complete noob dumbass. Thanks for coming to my Ted Talk.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsweetbbak%2Fcontainers-for-dummies","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsweetbbak%2Fcontainers-for-dummies","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsweetbbak%2Fcontainers-for-dummies/lists"}