https://github.com/samyak2/guntainer
A minimal rootless container runtime on Linux
https://github.com/samyak2/guntainer
containers go golang linux linux-namespaces
Last synced: 9 months ago
JSON representation
A minimal rootless container runtime on Linux
- Host: GitHub
- URL: https://github.com/samyak2/guntainer
- Owner: Samyak2
- License: mit
- Created: 2021-07-01T17:36:39.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2021-09-17T16:48:26.000Z (over 4 years ago)
- Last Synced: 2025-05-01T01:52:05.383Z (9 months ago)
- Topics: containers, go, golang, linux, linux-namespaces
- Language: Go
- Homepage:
- Size: 50.8 KB
- Stars: 5
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# guntainer
A minimal rootless container implementation on Linux. ~~Copied from~~ Inspired by Liz Rice's amazing [talk](https://youtu.be/8fi7uSYlOdc) on implementing containers from scratch.
## Features
- *Rootless*: never use `sudo` to run a container
- *Images*: guntainer can build container images, with a `Gunfile` to define the structure.
## Getting started
Install using (Go 1.16+ recommended):
```
go install github.com/Samyak2/guntainer@latest
```
(ensure `GOBIN` is in path)
Confirm that the installation succeeded.
```
guntainer help
```
To run a container image, use the `run` subcommand.
See [here](#run-examples) for more information and examples.
```
guntainer run --help
```
To build a container image using a `Gunfile`, use the `build` subcommand.
See [here](#building-images) for more information and examples.
```
guntainer build --help
```
## Building images
guntainer can build new images out of existing ones, in a similar way to `docker build`. Images are described using a `Gunfile`, whose format is very much a work-in-progress. Following is the structure of a Gunfile (at least the things that currently work):
```Gunfile
Using ""
Exec "some command"
```
More examples can be found [here](./examples/).
To build the image from [example_02](./examples/02_alpine_vim/), we can use:
```
guntainer build example_02.tar examples/02_alpine_vim/Gunfile
```
This will generate an `example_02.tar` which is the newly built image with `vim` installed. Run it using:
```
guntainer run example_02.tar /bin/sh
```
You should be able to use `vim` inside the container now.
## `run` Examples
These are examples of running an existing Linux distro inside guntainer.
### Alpine
Get the Alpine "mini root filesystem" from [here](https://alpinelinux.org/downloads/) ([direct link](https://dl-cdn.alpinelinux.org/alpine/v3.14/releases/x86_64/alpine-minirootfs-3.14.0-x86_64.tar.gz) of the specific version this was tested with).
Run the container with (replace the archive path if necessary) (you can also use `sh` instead of `ash`):
```sh
guntainer run alpine-minirootfs-3.14.0-x86_64.tar.gz /bin/ash
```
Most programs will work. Running `hostname` should say `guntainer`.
Internet will not work out of the box as no DNS servers are configured. Use the following to access internet (replace the IP address as necessary):
```sh
echo "nameserver 8.8.8.8" > /etc/resolv.conf
```
### Ubuntu
Get the Ubuntu Base image from [here](http://cdimage.ubuntu.com/ubuntu-base/releases/) ([direct link](http://cdimage.ubuntu.com/ubuntu-base/releases/21.04/release/ubuntu-base-21.04-base-amd64.tar.gz) to the specific version used).
Run using:
```sh
guntainer run ubuntu-base-21.04-base-amd64.tar.gz /bin/bash
```
Running `hostname` should say `guntainer`.
Issues:
- `apt` will not work out of the box. Refer [this](https://github.com/opencontainers/runc/issues/2517#issuecomment-657139999) thread for [details](https://github.com/opencontainers/runc/issues/2517#issuecomment-764163674).
Workaround (pls don't run this outside a container):
```sh
sed -i '/_apt/d' /etc/passwd
```
- Internet will not work out of the box. Workaround:
```sh
echo "nameserver 8.8.8.8" > /etc/resolv.conf
```
## TODO
- [x] Better CLI using [cobra](https://github.com/spf13/cobra)
- [ ] Use cgroups for resource limits
- [ ] (a bit ambitious) be OCI compliant
- [ ] Fix Ubuntu issues
- [x] Dockerfile equivalent
- [ ] Download images from URL, like go's package management
- [ ] Figure out how to store metadata along with the built image. Could do it similar to docker images (OCI) or do something more hacky.
- [ ] Optional logging - `-v` flag should enable more logs.
## Resources
If you're looking to implement your own container runtime, these links are great to start with:
- [Mythili Vutukuru's lecture](https://youtu.be/4BG-hE72r_I) on containers - provides a good overview of the Linux concepts behind containers (namespaces and cgroups)
- [Containers From Scratch by Liz Rice](https://youtu.be/8fi7uSYlOdc) - most of the code is from this talk. Liz Rice implements it live on the stage while explaining how it works.
- The corresponding [code respository](https://github.com/lizrice/containers-from-scratch) is a good reference and also links to another slide deck for implementing rootless containers
## Implementation details
- The root FS archive is extracted in a temporary directory and `chroot`ed into. The directory is cleaned up once the container exits.
- Rootless is implemented by mapping the current user's UID and GID to 0 (root) inside the container. This means that inside the container you are root while the same user outside the container is your user.
- The Gunfile is implemented [here](./gunfile/). It uses [participle](https://github.com/alecthomas/participle) to parse the Gunfile and build an AST.
- To save the built image I had to implement a custom tar wrapper to handle in-container symlinks. I called it [guntar](./guntar/).
## License
MIT