Add first draft

This commit is contained in:
Ketan Vijayvargiya 2023-12-30 06:12:15 +00:00
commit 749780c39d
4 changed files with 104 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
container-root
.idea

21
README.md Normal file
View file

@ -0,0 +1,21 @@
# containers-from-scratch
This repository contains my re-implementation of
[Containers From Scratch • Liz Rice • GOTO 2018](https://www.youtube.com/watch?v=8fi7uSYlOdc).
## Setup
One time setup:
```shell
docker run --rm -it ubuntu bash
# Copy contents of the container:
docker cp 9405abfa4a78:/ container-root
```
Then, just run the Go program as *root*:
```shell
sudo go run main.go run bash
```

3
go.mod Normal file
View file

@ -0,0 +1,3 @@
module containers-from-scratch
go 1.21.5

78
main.go Normal file
View file

@ -0,0 +1,78 @@
package main
import (
"fmt"
"os"
"os/exec"
"strconv"
"syscall"
"time"
)
// docker run <container-name> <command> <args>
// go main.go run <command> <args>
func main() {
if len(os.Args) < 3 {
panic("found too few arguments for the program.")
}
switch os.Args[1] {
case "run":
executeRun()
case "child":
executeChild()
default:
panic(fmt.Sprintf("found an unsupported command: %s", os.Args[0]))
}
}
func executeRun() {
fmt.Printf("starting: 'run' in PID: %d\n", os.Getpid())
cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS,
Unshareflags: syscall.CLONE_NEWNS,
}
must(cmd.Run())
}
func executeChild() {
fmt.Printf("starting: %s in PID: %d\n", os.Args[2], os.Getpid())
setupCgroup()
syscall.Sethostname([]byte("container"))
syscall.Chroot("./container-root")
os.Chdir("/")
syscall.Mount("proc", "proc", "proc", 0, "")
defer syscall.Unmount("/proc", 0)
cmd := exec.Command(os.Args[2])
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
must(cmd.Run())
}
func setupCgroup() {
cgroupDir := fmt.Sprintf("/sys/fs/cgroup/pids/%d", time.Now().Unix())
must(os.Mkdir(cgroupDir, 0755))
os.WriteFile(fmt.Sprintf("%s/pids.max", cgroupDir), []byte("20"), 0644)
os.WriteFile(fmt.Sprintf("%s/notify_on_release", cgroupDir), []byte("1"), 0644)
os.WriteFile(fmt.Sprintf("%s/cgroup.procs", cgroupDir), []byte(strconv.Itoa(os.Getpid())), 0644)
}
func must(err error) {
if err != nil {
panic(err)
}
}