{"id":16333392,"url":"https://github.com/mic92/cntr","last_synced_at":"2025-05-15T18:08:52.005Z","repository":{"id":8914702,"uuid":"60213548","full_name":"Mic92/cntr","owner":"Mic92","description":"A container debugging tool based on FUSE","archived":false,"fork":false,"pushed_at":"2024-04-30T09:17:22.000Z","size":593,"stargazers_count":638,"open_issues_count":32,"forks_count":23,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-05-02T00:15:55.256Z","etag":null,"topics":["build-with-buildbot","docker","lxc","managed-by-renovate","rkt","systemd-nspawn"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Mic92.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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}},"created_at":"2016-06-01T21:57:42.000Z","updated_at":"2024-05-03T07:44:02.389Z","dependencies_parsed_at":"2024-04-18T02:27:59.767Z","dependency_job_id":"6388cac3-bde5-4745-812a-283f95406a72","html_url":"https://github.com/Mic92/cntr","commit_stats":{"total_commits":360,"total_committers":5,"mean_commits":72.0,"dds":0.1444444444444445,"last_synced_commit":"58627cf1444f1827c1211a629d9e47c37371af8d"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mic92%2Fcntr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mic92%2Fcntr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mic92%2Fcntr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mic92%2Fcntr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Mic92","download_url":"https://codeload.github.com/Mic92/cntr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247744333,"owners_count":20988783,"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","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":["build-with-buildbot","docker","lxc","managed-by-renovate","rkt","systemd-nspawn"],"created_at":"2024-10-10T23:35:27.358Z","updated_at":"2025-04-07T23:08:23.865Z","avatar_url":"https://github.com/Mic92.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cntr\n\nSay no to `$ apt install vim` in containers!\n`cntr` is a replacement for `docker exec` that brings all your developers tools with you.\nThis is done by mounting the file system from one container or the host into the target container\nby creating a nested container with the help of a FUSE filesystem.\nThis allows to ship minimal runtime image in production and limit the surface for exploits.\n\nCntr was also published in [Usenix ATC 2018](https://www.usenix.org/conference/atc18/presentation/thalheim).\nSee [bibtex](#bibtex) for citation.\n\n## Demo\n\nIn this two minute recording you learn all the basics of cntr:\n\n[![asciicast](https://asciinema.org/a/PQB5RnRGLIPn88a1R2MtPccdy.png)](https://asciinema.org/a/PQB5RnRGLIPn88a1R2MtPccdy)\n\n## Features\n\n- For convenience cntr supports container names/identifier for the following container engines natively:\n  * docker\n  * podman\n  * LXC\n  * LXD\n  * rkt\n  * systemd-nspawn\n  * containerd\n- For other container engines cntr also takes process ids (PIDs) instead of container names.\n\n## Installation\n\nCntr can be only supports linux.\n\n### Pre-build static-linked binary\n\nFor linux x86_64 we build static binaries for every release. More platforms can added on request.\nSee the [release tab](https://github.com/Mic92/cntr/releases/) for pre-build tarballs.\nAt runtime only commandline utils of the container engine in questions are required.\n\n### Build from source\n\nAll you need for compilation is rust + cargo.\nCheckout [rustup.rs](https://rustup.rs/) on how to get a working rust toolchain.\nThen run:\n\nEither:\n\n```console\n$ cargo install cntr\n```\n\nOr the latest master:\n\n```console\n$ cargo install --git https://github.com/Mic92/cntr\n```\n\nFor offline builds we also provided a tarball with all dependencies bundled\n[here](https://github.com/Mic92/cntr/releases) for compilation with\n[cargo-vendor](https://github.com/alexcrichton/cargo-vendor).\n\n## Usage\n\nAt a high-level cntr provides two subcommands: `attach` and `exec`:\n\n- `attach`: Allows you to attach to a container with your own native shell/commands.\n  Cntr will mount the container at `/var/lib/cntr`.\n  The container itself will run unaffected as the mount changes are not visible to container processes.\n  - Example: `cntr attach \u003ccontainer_id\u003e` where `container_id` can be a\n    container identifier or process id (see examples below).\n- `exec`: Once you are in the container, you can also run commands from the\n  container filesystem itself. Since those might need their native mount layout\n  at `/` instead of `/var/lib/cntr`, cntr provides `exec` subcommand to chroot to container\n  again and also resets the environment variables that might have been changed\n  by the shell.\n  - Example: `cntr exec \u003ccommand\u003e` where `command` is an executable in the container\n\n**Note**: Cntr needs to run on the same host as the container. It does not work\nif the container is running in a virtual machine while cntr is running on the\nhypervisor.\n\n```console\n$ cntr --help\nCntr 1.5.1\nJörg Thalheim \u003cjoerg@thalheim.io\u003e\nEnter or executed in container\n\nUSAGE:\n    cntr \u003cSUBCOMMAND\u003e\n\nFLAGS:\n    -h, --help       Prints help information\n    -V, --version    Prints version information\n\nSUBCOMMANDS:\n    attach    Enter container\n    exec      Execute command in container filesystem\n    help      Prints this message or the help of the given subcommand(s)\n```\n\n```console\n$ cntr attach --help\ncntr-attach 1.5.1\nJörg Thalheim \u003cjoerg@thalheim.io\u003e\nEnter container\n\nUSAGE:\n    cntr attach [OPTIONS] \u003cid\u003e [command]...\n\nFLAGS:\n    -h, --help    Prints help information\n\nOPTIONS:\n        --effective-user \u003cEFFECTIVE_USER\u003e    effective username that should be owner of new created files on the host\n    -t, --type \u003cTYPE\u003e                        Container types to try (sperated by ','). [default: all but command]\n                                             [possible values: process_id, rkt, podman, docker, nspawn, lxc, lxd,\n                                             containerd, command]\n\nARGS:\n    \u003cid\u003e            container id, container name or process id\n    \u003ccommand\u003e...    Command and its arguments to execute after attach. Consider prepending it with '-- ' to prevent\n                    parsing of '-x'-like flags. [default: $SHELL]\n```\n\n```console\n$ cntr exec --help\ncntr-exec 1.5.1\nJörg Thalheim \u003cjoerg@thalheim.io\u003e\nExecute command in container filesystem\n\nUSAGE:\n    cntr exec [command]...\n\nFLAGS:\n    -h, --help       Prints help information\n    -V, --version    Prints version information\n\nARGS:\n    \u003ccommand\u003e...    Command and its arguments to execute after attach. Consider prepending it with '-- ' to prevent\n                    parsing of '-x'-like flags. [default: $SHELL]\n```\n\n### Docker\n\n1: Find out the container name/container id:\n```console\n$ docker run --name boxbusy -ti busybox\n$ docker ps\nCONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES\n55a93d71b53b        busybox             \"sh\"                22 seconds ago      Up 20 seconds                           boxbusy\n```\n\nEither provide a container id...\n\n```console\n$ cntr attach 55a93d71b53b\n[root@55a93d71b53b:/var/lib/cntr]# echo \"I am in a container!\"\n[root@55a93d71b53b:/var/lib/cntr]# ip addr\n1: lo: \u003cLOOPBACK,UP,LOWER_UP\u003e mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000\n    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\n    inet 127.0.0.1/8 scope host lo\n       valid_lft forever preferred_lft forever\n40: eth0@if41: \u003cBROADCAST,MULTICAST,UP,LOWER_UP\u003e mtu 1500 qdisc noqueue state UP group default\n    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0\n    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0\n       valid_lft forever preferred_lft forever\n[root@55a93d71b53b:/var/lib/cntr]# vim etc/resolv.conf\n```\n\n...or the container name.\nUse `cntr exec` to execute container native commands (while running in the cntr shell).\n\n```console\n$ cntr attach boxbusy\n[root@55a93d71b53b:/var/lib/cntr]# cntr exec -- sh -c 'busybox | head -1'\n```\n\nYou can also use Dockerfile from this repo to build a docker container with cntr:\n\n``` console\n$ docker build -f Dockerfile . -t cntr\n# boxbusy here is the name of the target container to attach to\n$ docker run --pid=host --privileged=true -v /var/run/docker.sock:/var/run/docker.sock -ti --rm cntr attach boxbusy /bin/sh\n```\n\n### Podman\n\nSee docker usage, just replace `docker` with the `podman` command.\n\n\n### LXD\n\n1: Create a container and start it\n\n```console\n$ lxc image import images:/alpine/edge\n$ lxc launch images:alpine/edge\n$ lxc list\n+-----------------+---------+------+------+------------+-----------+\n|      NAME       |  STATE  | IPV4 | IPV6 |    TYPE    | SNAPSHOTS |\n+-----------------+---------+------+------+------------+-----------+\n| amazed-sailfish | RUNNING |      |      | PERSISTENT | 0         |\n+-----------------+---------+------+------+------------+-----------+\n```\n\n2: Attach to the container with cntr\n\n```console\n$ cntr attach amazed-sailfish\n$ cat etc/hostname\namazed-sailfish\n```\n\n### LXC\n\n1: Create a container and start it\n\n```console\n$ lxc-create --name ubuntu -t download -- -d ubuntu -r xenial -a amd64\n$ lxc-start --name ubuntu -F\n...\nUbuntu 16.04.4 LTS ubuntu console\nubuntu login:\n$ lxc-ls\nubuntu\n```\n\n2: Attach to container with cntr:\n\n```console\n$ cntr attach ubuntu\n[root@ubuntu2:/var/lib/cntr]# cat etc/os-release\nNAME=\"Ubuntu\"\nVERSION=\"16.04.4 LTS (Xenial Xerus)\"\nID=ubuntu\nID_LIKE=debian\nPRETTY_NAME=\"Ubuntu 16.04.4 LTS\"\nVERSION_ID=\"16.04\"\nHOME_URL=\"http://www.ubuntu.com/\"\nSUPPORT_URL=\"http://help.ubuntu.com/\"\nBUG_REPORT_URL=\"http://bugs.launchpad.net/ubuntu/\"\nVERSION_CODENAME=xenial\nUBUNTU_CODENAME=xenial\n```\n\n### rkt\n\n1: Find out the container uuid:\n\n```console\n$ rkt run --interactive=true docker://busybox\n$ rkt list\nUUID            APP     IMAGE NAME                                      STATE   CREATED         STARTED         NETWORKS\nc2d2e87e        busybox registry-1.docker.io/library/busybox:latest     running 6 minutes ago   6 minutes ago   default:ip4=172.16.28.3\n```\n\n2: Attach with cntr\n\n```console\n# make sure your container is still running!\n$ cntr attach c2d2e87e\n# Finally not the old ugly top!\n[gen0@rkt-c2d2e87e-e798-4341-ae93-26f6cbb7c017:/var/lib/cntr]# htop\n...\n```\n\nWith cntr you can also debug stage1 of rkt - even there is no support from rkt itself.\n\n```console\n$ ps aux | grep stage1\njoerg    13546  0.0  0.0 120808  1608 pts/12   S+   11:10   0:00 grep --binary-files=without-match --directories=skip --color=auto stage1\nroot     22232  0.0  0.0  54208  2656 pts/7    S+   10:54   0:00 stage1/rootfs/usr/lib/ld-linux-x86-64.so.2 stage1/rootfs/usr/bin/systemd-nspawn --boot --notify-ready=yes --register=true --link-journal=try-guest --quiet --uuid=c2d2e87e-e798-4341-ae93-26f6cbb7c017 --machine=rkt-c2d2e87e-e798-4341-ae93-26f6cbb7c017 --directory=stage1/rootfs --capability=CAP_AUDIT_WRITE,CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FSETID,CAP_FOWNER,CAP_KILL,CAP_MKNOD,CAP_NET_RAW,CAP_NET_BIND_SERVICE,CAP_SETUID,CAP_SETGID,CAP_SETPCAP,CAP_SETFCAP,CAP_SYS_CHROOT -- --default-standard-output=tty --log-target=null --show-status=0\n```\n\nTherefore we use the process id instead of the container uuid:\n\n```console\n$ cntr attach 22232\n# new and exiting territory!\n[root@turingmachine:/var/lib/cntr]# mount | grep pods\nsysfs on /var/lib/cntr/var/lib/rkt/pods/run/c2d2e87e-e798-4341-ae93-26f6cbb7c017/stage1/rootfs/sys type sysfs (ro,nosuid,nodev,noexec,relatime)\ntmpfs on /var/lib/cntr/var/lib/rkt/pods/run/c2d2e87e-e798-4341-ae93-26f6cbb7c017/stage1/rootfs/sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)\ncgroup on /var/lib/cntr/var/lib/rkt/pods/run/c2d2e87e-e798-4341-ae93-26f6cbb7c017/stage1/rootfs/sys/fs/cgroup/memory type cgroup (ro,nosuid,nodev,noexec,relatime,memory)\n```\n\n### systemd-nspawn\n\n1: Start container\n\n```console\n$ wget https://cloud-images.ubuntu.com/releases/16.04/release/ubuntu-16.04-server-cloudimg-amd64-root.tar.xz\n$ mkdir /var/lib/machines/ubuntu\n$ tar -xf ubuntu-16.04-server-cloudimg-amd64-root.tar.xz -C /var/lib/machines/ubuntu\n$ systemd-nspawn -b -M ubuntu\n$ machinectl list\nMACHINE CLASS     SERVICE        OS     VERSION ADDRESSES\nubuntu  container systemd-nspawn ubuntu 16.04   -\n```\n\n2: Attach\n```console\n$ cntr attach ubuntu\n```\n\n### Generic process id\n\nThe minimal information needed by cntr is the process id of a container process you want to attach to.\n\n```console\n# Did you now chromium uses namespaces too?\n$ ps aux | grep 'chromium --type=renderer'\njoerg    17498 11.7  1.0 1394504 174256 ?      Sl   15:16   0:08 /usr/bin/chromium\n```\n\nIn this case 17498 is the pid we are looking for.\n\n```console\n$ cntr attach 17498\n# looks quite similar to our system, but with less users\n[joerg@turingmachine cntr]$ ls -la /\ntotal 240\ndrwxr-xr-x   23 nobody nogroup    23 Mar 13 15:05 .\ndrwxr-xr-x   23 nobody nogroup    23 Mar 13 15:05 ..\ndrwxr-xr-x    2 nobody nogroup     3 Mar 13 15:14 bin\ndrwxr-xr-x    4 nobody nogroup 16384 Jan  1  1970 boot\ndrwxr-xr-x   24 nobody nogroup  4120 Mar 13 14:56 dev\ndrwxr-xr-x   52 nobody nogroup   125 Mar 13 15:14 etc\ndrwxr-xr-x    3 nobody nogroup     3 Jan  8 16:17 home\ndrwxr-xr-x    8 nobody nogroup     8 Feb  9 22:10 mnt\ndr-xr-xr-x  306 nobody nogroup     0 Mar 13 09:38 proc\ndrwx------   22 nobody nogroup    43 Mar 13 15:09 root\n...\n```\n\n### Containerd\n\nFor containerd integration the `ctr` binary is required. You can get a binary by running:\n\n``` console\n$ GOPATH=$(mktemp -d)\n$ go get github.com/containerd/containerd/cmd/ctr\n$ $GOPATH/bin/ctr --help\n```\n\nPut the resulting `ctr` binary in your `$PATH`\n\n1: Start container\n```console\n$ ctr images pull docker.io/library/busybox:latest\n$ ctr run docker.io/library/busybox:latest boxbusy\n$ ctr tasks lists\nTASK        PID      STATUS\nboxbusy    24310    RUNNING\n```\n\n2: Attach\n```console\n$ cntr attach boxbusy\n```\n\nIt's also possible to run cntr from a container itself.\nThis repository contains a example Dockerfile for that:\n\n```console\n$ docker build -f Dockerfile.example . -t cntr\n$ docker save cntr \u003e cntr.tar\n$ ctr images import --base-name cntr ./cntr.tar\n```\n\nIn this example we attach to containerd by process id. The process id of a task is given in `ctr tasks list`.\n\n```console\n$ ctr run --privileged --with-ns pid:/proc/1/ns/pid --tty docker.io/library/cntr:latest cntr /usr/bin/cntr attach 31523 /bin/sh\n```\n\nTo resolve containerd names one also would need to add the `ctr` binary (~12mb) to the Dockerfile.\n\n## Additional Config\n\n### ZFS\n\n`cntr` requires POSIX ACLs be enabled under ZFS. By default, Linux ZFS doesn't have POSIX ACLs enabled. This results in\nthe following error when trying to `attach`:\n\n```console\nunable to move container mounts to new mountpoint: EOPNOTSUPP: Operation not supported on transport endpoint\n```\n\nTo enable POSIX ACLs on the ZFS dataset:\n\n```console\n$ zfs set acltype=posixacl zpool/media\n$ zfs set xattr=sa zpool/media              #  optional, but encouraged for best performance\n```\n\n# How it works\n\nCntr is container-agnostic: Instead of interfacing with container engines, it\nimplements the underlying operating system API. It treats every container as a\ngroup of processes, that it can inherit properties from.\n\nCntr inherits the following container properties:\n  * Namespaces (mount, uts, pid, net, cgroup, ipc)\n  * Cgroups\n  * Apparamor/selinux\n  * Capabilities\n  * User/group ids\n  * Environment variables\n  * The following files: /etc/passwd, /etc/hostname, /etc/hosts, /etc/resolv.conf\n\nUnder the hood it spawns a shell or user defined program that inherits the full\ncontext of the container and mount itself as a fuse filesystem.\n\nWe extensively evaluated the correctness and performance of cntr's filesystem\nusing [xfstests](https://github.com/Mic92/xfstests-cntr) and a wide range of\nfilesystem performance benchmarks (iozone, pgbench, dbench, fio, fs-mark,\npostmark, ...)\n\n# Related projects\n- [nsenter](https://manpages.debian.org/testing/manpages-de/nsenter.1.de.html)\n  - Only covers linux namespaces and the user is limited to tools installed in the\n    containers\n- [toolbox](https://github.com/coreos/toolbox)\n  - Does attach from a container to the host, this is the opposite of what Cntr\n    is doing\n\n# Bibtex\n\nWe published a paper with all technical details about Cntr in\n[Usenix ATC 2018](https://www.usenix.org/conference/atc18/presentation/thalheim).\n\n```bibtex\n@inproceedings{cntr-atc18,\n  author = {J{\\\"o}rg Thalheim and Pramod Bhatotia and Pedro Fonseca and Baris Kasikci},\n  title = {Cntr: Lightweight {OS} Containers},\n  booktitle = {2018 {USENIX} Annual Technical Conference ({USENIX} {ATC} 18)},\n  year = {2018},\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmic92%2Fcntr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmic92%2Fcntr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmic92%2Fcntr/lists"}