cntnr

command module
v0.0.0-...-ed4b4ac Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 22, 2018 License: Apache-2.0 Imports: 2 Imported by: 0

README

cntnr

CNTNR DEVELOPMENT IS IN AN EARLY STATE!

cntnr is a container engine library and CLI built on top of runc to manage and build OCI images as well as containers.
cntnr aims to ease system container creation and execution as unprivileged user. Besides cntnr is a platform to try out new runc features.

Features

  • OCI bundle and container preparation as well as execution as unprivileged user using runc
  • OCI image build as unprivileged user
  • Simple concurrently accessible image and bundle store
  • Image and bundle file system creation using umoci
  • Various image formats and transports supported by containers/image
  • Container networking using CNI (optional, as OCI runtime hook)
  • Docker Compose 3 support (subset) using docker/cli
  • Easy to learn: docker-like CLI
  • Easy installation: single statically linked binary (plus optional binaries: CNI plugins, proot) and convention over configuration

Rootless containers

Concerning accessibility, usability and security container engines that do not require root privileges have several advantages compared to those that do:

  • Containers can be run by unprivileged users.
    Required in restrictive environments and useful for graphical applications.
  • Container images can be built almost in every Linux environment.
    Higher flexibility in unprivileged CI/CD build jobs - running a container in a container is already possible (see limitations and experiments below).
  • A higher degree and more flexible level of security.
    Less likely for an attacker to gain root access through a possible engine security leak when run as unprivileged user.
    User/group-based container access control leveraging the host OS' ACL.
Limitations & challenges

Container execution as unprivileged user is limited:

Container networks cannot be configured. As a result in a restrictive environment without root access only the host network can be used. A feature on the roadmap is a daemon that runs as root and can configure a separate container namespace for an unprivileged user's container.

Inside the container a process' or file's user cannot be changed. This is caused by the fact that all operations in the container are still run by the host user who is mapped to a user inside the container. Unfortunately this stops many package managers as well as official docker images from working.
A solution approach is to hook the kernel-space system calls and prevent their propagation to the kernel. Though this does not solve the whole problem since applications that rely on or check the state they assume to have changed previously using such a fake system call will still not work.
While apk already works with plain runc apt-get does not. To also make software like apt-get work other implementations as namely fakechroot (using LD_PRELOAD), remainroot (using ptrace) or PRoot (using ptrace) can be used. PRoot can be used in cntnr with the --proot flag when installed on your system (using ./contrib/install-proot.sh).

For more details see Aleksa Sarai's summary of the state of the art of rootless containers.

Build

Build the binary dist/bin/cntnr as well as dist/bin/cni-plugins on a Linux machine with git, make and docker:

git clone https://github.com/mgoltzsche/cntnr.git
cd cntnr
make

Install in /usr/local:

sudo make install

Optionally the project can now be opened with LiteIDE running in a cntnr container
(Please note that it takes some time to build the LiteIDE container image):

make ide

Examples

The following examples assume your policy accepts docker images or you have copied policy-example.json to /etc/containers/policy.json on your host.

Create and run container from Docker image
> cntnr run docker://alpine:3.7 echo hello world
hello world
Create and run Firefox as unprivileged user

Build a Firefox ESR container image local/firefox:alpine (cached operation):

cntnr image create \
	--from=docker://alpine:3.7 \
	--author='John Doe' \
	--run='apk add --update --no-cache firefox-esr libcanberra-gtk3 adwaita-icon-theme ttf-ubuntu-font-family' \
	--cmd=firefox \
	--tag=local/firefox:alpine

Create and run a bundle named firefox from the previously built image:

cntnr run -b firefox --update \
	--env DISPLAY=$DISPLAY \
	--mount /tmp/.X11-unix:/tmp/.X11-unix \
	--mount /etc/machine-id:/etc/machine-id:ro \
	local/firefox:alpine

The -b <BUNDLE> and --update options make this operation idempotent: The bundle's file system is reused and only recreated when the underlying image has changed. Use these options to restart containers very quickly. Without them cntnr copies the image file system on bundle creation which can take some time and disk space depending on the image's size.
Also these options enable a container update on restart when the base image is frequently updated before the child image is rebuilt using the following command:

cntnr image import docker://alpine:3.7

The OCI standard and this implementation

An OCI image provides a base configuration and file system to create an OCI bundle from. The file system consists of a list of layers which are represented by archive files each containing the diff to its parent.
cntnr manages images in its local store directory in the OCI image layout format. Images are imported into the local store using the containers/image library. A new bundle is created by extracting the image's file system into a directory using umoci and deriving the bundle's default configuration from the image's configuration.

An OCI bundle describes a container by a configuration and a file system. Basically it is a directory containing a config.json file with the configuration and a sub directory with the root file system.
cntnr manages bundles in its local store directory. Alternatively a custom directory can also be used as bundle. OCI bundles generated by cntnr can also be run with other OCI-compliant container engines as runc.

An OCI container is a host-specific bundle instance. On Linux it is a set of namespaces in which a configured process can be run.
cntnr provides two wrapper implementations of the OCI runtime reference implementation runc/libcontainer to either use an external runc binary or use libcontainer (no runtime dependencies!) controlled by a compiler flag.

Roadmap

  • separate OCI hook binary
  • Dockerfile support
  • garbage collection for containers, build caches, mtrees
  • improved multi-user support (store per user group, file permissions, lock location)
  • integration tests
  • 0.7 beta release
  • more integration and unit tests
  • improved garbage collection options for images
  • improved Docker Compose support
  • service discovery integration (hook / DNS; consul, etcd)
  • health check
  • daemon mode
  • systemd integration (cgroup, startup notification)
  • 1.0 release
  • advanced logging
  • support for additional read-only image stores
  • optional network manager daemon with ACL to be used by unprivileged users to configure their container networks
  • far future: make it available on platforms other than Linux

Experiments

Experiments with nested containers

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
builder/dockerfile/shell
This package is part of a workaround to get the docker parser without its dependencies.
This package is part of a workaround to get the docker parser without its dependencies.
store
See https://github.com/containers/image/blob/master/docs/policy.json.md
See https://github.com/containers/image/blob/master/docs/policy.json.md
oci
pkg
log
run
librunner
This file is derived from opencontainers/runc/tty.go and opencontainers/runc/utils_linux.go (setupIO)
This file is derived from opencontainers/runc/tty.go and opencontainers/runc/utils_linux.go (setupIO)
store_old
oci

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL