SkillAgentSearch skills...

Cntr

A container debugging tool based on FUSE

Install / Use

/learn @Mic92/Cntr
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

cntr

Say no to $ apt install vim in containers! cntr is a replacement for docker exec that brings all your developers tools with you. This is done by mounting the file system from one container or the host into the target container by creating a nested container with the help of the Linux mount API. This allows to ship minimal runtime image in production and limit the surface for exploits.

Requirements: Linux kernel 5.2 or later (uses fsopen/fsmount mount API, added in 5.2).

Cntr was also published in Usenix ATC 2018. See bibtex for citation.

Note: The academic paper describes the original FUSE-based architecture. As of version 2.0.0, cntr has been rewritten to use the Linux mount API instead of FUSE, significantly improving performance and security while maintaining the same user interface and capabilities.

What you get

graph TB
    User([User runs: cntr attach container_id])

    User -->|attach| Shell

    subgraph Shell["Your Shell Inside Container"]
        HostTools["✓ Your host tools available<br/>/usr/bin/vim, /usr/bin/htop, /home/user/.config"]
        ContainerFS["✓ Container filesystem at /var/lib/cntr/"]
        ContainerEnv["✓ Container environment<br/>network, PIDs, hostname"]
        Exec["✓ Run container commands via cntr exec"]
    end

    Shell -.->|shares namespace| Container["Running Container<br/>(unaffected)"]

    style Shell fill:#e8f5e9
    style User fill:#e3f2fd
    style Container fill:#fff3e0

What this means for you:

  • Use your familiar tools (vim, gdb, strace) even if they're not in the container
  • Access container files at /var/lib/cntr/etc/, /var/lib/cntr/var/, etc.
  • Same network, process tree, and environment as the container
  • Original container keeps running normally - your changes only affect your session
  • Run native container commands with cntr exec

Demo

In this two minute recording you learn all the basics of cntr:

asciicast

Features

  • For convenience cntr supports container names/identifier for the following container engines natively:
    • docker
    • podman
    • LXC
    • LXD
    • systemd-nspawn
    • containerd
    • k3s (via containerd/crictl)
  • For other container engines cntr also takes process ids (PIDs) instead of container names.

Installation

Cntr by design is only able to run on Linux.

System Requirements:

  • Linux kernel 5.2 or later

For distribution packagers: See PACKAGING.md for packaging guidelines and examples.

Pre-build static-linked binary

For linux x86_64 we build static binaries for every release. More platforms can added on request. See the release tab for pre-build tarballs. At runtime only commandline utils of the container engine in questions are required.

Build from source

All you need for compilation is rust + cargo. Checkout rustup.rs on how to get a working rust toolchain. Then run:

Either:

$ cargo install cntr

Or the latest master:

$ cargo install --git https://github.com/Mic92/cntr

For offline builds we also provided a tarball with all dependencies bundled here for compilation with cargo-vendor.

Usage

At a high-level cntr provides two subcommands: attach and exec:

  • attach: Allows you to attach to a container with your own native shell/commands. Cntr will mount the container at /var/lib/cntr (configurable via CNTR_BASE_DIR environment variable). The container itself will run unaffected as the mount changes are not visible to container processes.
    • Example: cntr attach <container_id> where container_id can be a container identifier or process id (see examples below).
  • exec: Run commands from the container filesystem.
    • Usage: cntr exec <container_id> -- <command>
    • Example: cntr exec <container_id> where container_id can be a container identifier or process id Since container commands might need their native mount layout at /, exec chroots to the container and sets up the container's environment.

Note: Cntr needs to run on the same host as the container. It does not work if the container is running in a virtual machine while cntr is running on the hypervisor.

$ cntr --help
cntr 1.6.1
by Jörg Thalheim <joerg@thalheim.io>

Enter or execute in container

USAGE:
    cntr <SUBCOMMAND>

SUBCOMMANDS:
    attach    Enter container with mount overlay
    exec      Execute command in container
    help      Print help
    version   Print version
$ cntr attach --help
cntr-attach 1.6.1
by Jörg Thalheim <joerg@thalheim.io>

USAGE:
    cntr attach [OPTIONS] <CONTAINER_ID> [-- <COMMAND>...]

ARGS:
    <CONTAINER_ID>    Container ID, name, or process ID

OPTIONS:
    -t, --type <TYPES>           Container types to try (comma-separated)
                                 [possible: process-id,podman,docker,nspawn,lxc,lxd,containerd,command,kubernetes]
                                 [default: all but command]
    --effective-user <USER>      Effective username for new files on host
    --apparmor <MODE>            AppArmor profile mode
                                 [possible: auto, off]
                                 [default: auto]
    -h, --help                   Print help
    -V, --version                Print version

COMMAND:
    Command and arguments to execute [default: $SHELL]
    Use '--' to separate command from options
$ cntr exec --help
cntr-exec 1.6.1
by Jörg Thalheim <joerg@thalheim.io>

USAGE:
    cntr exec [OPTIONS] <CONTAINER_ID> [-- <COMMAND>...]

ARGS:
    <CONTAINER_ID>    Container ID, name, or process ID (required)

OPTIONS:
    -t, --type <TYPES>           Container types to try (comma-separated)
                                 [possible: process-id,podman,docker,nspawn,lxc,lxd,containerd,command,kubernetes]
                                 [default: all but command]
    --apparmor <MODE>            AppArmor profile mode
                                 [possible: auto, off]
                                 [default: auto]
    -h, --help                   Print help
    -V, --version                Print version

COMMAND:
    Command and arguments to execute [default: /bin/sh]
    Use '--' to separate command from options

Docker

1: Find out the container name/container id:

$ docker run --name boxbusy -ti busybox
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
55a93d71b53b        busybox             "sh"                22 seconds ago      Up 20 seconds                           boxbusy

Either provide a container id...

$ cntr attach 55a93d71b53b
[root@55a93d71b53b:/var/lib/cntr]# echo "I am in a container!"
[root@55a93d71b53b:/var/lib/cntr]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
40: eth0@if41: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
[root@55a93d71b53b:/var/lib/cntr]# vim etc/resolv.conf

...or the container name.

To execute container native commands, use cntr exec:

$ cntr exec boxbusy -- sh -c 'busybox | head -1'

You can also use Dockerfile from this repo to build a docker container with cntr:

$ docker build -f Dockerfile . -t cntr
# boxbusy here is the name of the target container to attach to
$ docker run --pid=host --privileged=true -v /var/run/docker.sock:/var/run/docker.sock -ti --rm cntr attach boxbusy /bin/sh

Podman

See docker usage, just replace docker with the podman command.

LXD

1: Create a container and start it

$ lxc image import images:/alpine/edge
$ lxc launch images:alpine/edge
$ lxc list
+-----------------+---------+------+------+------------+-----------+
|      NAME       |  STATE  | IPV4 | IPV6 |    TYPE    | SNAPSHOTS |
+-----------------+---------+------+------+------------+-----------+
| amazed-sailfish | RUNNING |      |      | PERSISTENT | 0         |
+-----------------+---------+------+------+------------+-----------+

2: Attach to the container with cntr

$ cntr attach amazed-sailfish
$ cat etc/hostname
amazed-sailfish

LXC

1: Create a container and start it

$ lxc-create --name ubuntu -t download -- -d ubuntu -r xenial -a amd64
$ lxc-start --name ubuntu -F
...
Ubuntu 16.04.4 LTS ubuntu console
ubuntu login:
$ lxc-ls
ubuntu

2: Attach to container with cntr:

$ cntr attach ubuntu
[root@ubuntu2:/var/lib/cntr]# cat etc/os-release
NAME="Ubuntu"
VERSION="16.04.4 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.4 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial

systemd-nspawn

1: Start container

$ wget https://cloud-images.ubuntu.com/releases/16.04/release/ubuntu-16.04-server-cloudimg-amd64-root.tar.xz
$ mkdir /var/lib/machines/ubuntu
$ tar -xf ubuntu-16.04-server-cloudimg-amd64-root.tar.xz -C /var/lib/machines/ubuntu
$ systemd-nspawn -b -M ubuntu
$ machinectl list
MACHINE CLASS     SERVICE        OS     VERSION ADDRESSES
ubuntu  container systemd-nspawn ubuntu 16.04   -

2: Attach

$ cntr attach u
View on GitHub
GitHub Stars910
CategoryDevelopment
Updated23h ago
Forks25

Languages

Rust

Security Score

100/100

Audited on Mar 23, 2026

No findings