{"id":27283886,"url":"https://github.com/purplesyringa/docker-boot","last_synced_at":"2025-08-17T12:33:37.974Z","repository":{"id":233263481,"uuid":"786393621","full_name":"purplesyringa/docker-boot","owner":"purplesyringa","description":"Like `execve`, but for userspace","archived":false,"fork":false,"pushed_at":"2024-05-29T07:48:24.000Z","size":16,"stargazers_count":151,"open_issues_count":0,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-11T18:54:15.872Z","etag":null,"topics":["docker","just-for-fun"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"wtfpl","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/purplesyringa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-04-14T10:25:28.000Z","updated_at":"2025-03-28T13:57:43.000Z","dependencies_parsed_at":null,"dependency_job_id":"4b59f8b9-c836-4a94-8f0e-01c23eb1d371","html_url":"https://github.com/purplesyringa/docker-boot","commit_stats":null,"previous_names":["purplesyringa/docker-boot"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/purplesyringa/docker-boot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purplesyringa%2Fdocker-boot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purplesyringa%2Fdocker-boot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purplesyringa%2Fdocker-boot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purplesyringa%2Fdocker-boot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/purplesyringa","download_url":"https://codeload.github.com/purplesyringa/docker-boot/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purplesyringa%2Fdocker-boot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270850052,"owners_count":24656441,"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","status":"online","status_checked_at":"2025-08-17T02:00:09.016Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["docker","just-for-fun"],"created_at":"2025-04-11T18:46:32.492Z","updated_at":"2025-08-17T12:33:37.892Z","avatar_url":"https://github.com/purplesyringa.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# docker-boot\n\nhttps://github.com/purplesyringa/docker-boot/assets/16370781/0f2a24e1-7c5f-47a6-9730-479f853af25a\n\n\u003e Like `execve`, but for userspace.\n\ndocker-boot replaces your current running system with an in-memory root filesystem constructed from a Docker image.\n\nExample with GUI:\n\n**Dockerfile**\n\n```dockerfile\nFROM ubuntu\nRUN apt update\nRUN apt-get install -y software-properties-common \u0026\u0026 add-apt-repository ppa:mozillateam/ppa\nRUN DEBIAN_FRONTEND=noninteractive apt-get install -y sudo htop systemd sddm kde-plasma-desktop firefox-esr\nRUN useradd --create-home --shell /bin/bash --groups sudo --password \"$(perl -e \"print crypt('cutie', 'sa');\")\" --user-group purplesyringa\nRUN echo \"InputMethod=\" \u003e/etc/sddm.conf\n```\n\n```shell\n$ docker build . -t workstation\n\u003c...\u003e\n\n$ sudo docker-boot workstation /bin/systemd\n\u003cThe host system is shut down, Ubuntu with lightdm/KDE starts\u003e\n```\n\nExample without GUI:\n\n**Dockerfile**\n\n```shell\n$ sudo docker-boot ubuntu /bin/bash -c \"mount -t proc proc proc; mount -t sysfs sys sys; exec bash -i\"\n\u003cThe host system is shut down, Ubuntu starts in single-user mode\u003e\n```\n\n(Or make `systemd` mount the filesystems for you if you're feeling adventurous.)\n\n\n## Building\n\nJust do `make`.\n\nYou're going to need `docker`, `swapoff`, `tar`, and `dd` installed.\n\n\n## Why?\n\n1. I'm a Nix contrarian, so naturally I wanted *something* to be to Docker like NixOS is to Nix. docker-boot fills this niche.\n2. Injecting into `init` is based, I've always wanted to do that; this project is my excuse.\n3. If you need to move partitions on your boot disk, you probably want to run a system off RAM. This is typically accomplished by creating a tmpfs, `debootstrap`ing an OS into it, `pivot_root`ing and killing services that use the real disk. That's a bit ridiculous of a manual; this project attempts to reduce the gap.\n\n\n## How it works\n\nFirst, `docker-boot` creates a directory at `/run/dboot/root`, mounts `tmpfs` on top of it, and exports the Docker image there. Other useful metadata, such as the program to launch as `init` from the image, is stored in other files in `/run/dboot`.\n\n`docker-boot` then attaches to PID 1 via ptrace, just like a debugger would. It waits for init (typically `systemd`) to start a syscall and interrupts the process just before the syscall is executed. Processor registers are then updated in the process to execute another syscall in place of the one intended by real `init`.\n\nThe substituted syscall is `execve(\"/proc/\u003cpid\u003e/exe\", {\"dboot\", NULL}, NULL)`, where the `\u003cpid\u003e` is the PID of the `docker-boot` process. The path `/proc/\u003cpid\u003e/exe` refers to the executable of the corresponding process, so this is an easy way to replace PID 1 with a copy of `docker-boot` regardless of (the length of) the path to `docker-boot`. The strings `/proc/\u003cpid\u003e/exe` and `dboot` are stored below the red zone, i.e. 128 bytes below `rsp`. That is a region of stack that is almost always safe to overwrite.\n\n`docker-boot` then asks the kernel to execute exactly one instruction in the `init` process and checks whether the `errno` is `0`. If not, the `execve` is assumed to have failed, and the processor registers are restored to the state before `execve`, so that the system can keep functioning.\n\nOn success, `docker-boot` continues execution in PID 1. It switches graphics to TTY 3, kills all processes, and switches the root filesystem to `/run/dboot/root` via `pivot_root`, which is a more robust and modern alternative to `chroot` that allows `docker-boot` to safely unmount the host filesystem after changing roots. Finally, the process uses `execve` to execute the process requested by the user, typically systemd or a shell.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurplesyringa%2Fdocker-boot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpurplesyringa%2Fdocker-boot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurplesyringa%2Fdocker-boot/lists"}