Skip to content

Commit

Permalink
Merge pull request #29 from Mic92/containerd
Browse files Browse the repository at this point in the history
add containerd support
  • Loading branch information
Mic92 authored Dec 17, 2020
2 parents 2480804 + eb07c3c commit 9d23b59
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 1 deletion.
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ In this two minute recording you learn all the basics of cntr:
* LXD
* rkt
* systemd-nspawn
* containerd
- For other container engines cntr also takes process ids (PIDs) instead of container names.

## Installation
Expand Down Expand Up @@ -304,6 +305,50 @@ drwx------ 22 nobody nogroup 43 Mar 13 15:09 root
...
```

### Containerd

For containerd integration the `ctr` binary is required. You can get a binary by running:

``` console
$ GOPATH=$(mktemp -d)
$ go get github.com/containerd/containerd/cmd/ctr
$ $GOPATH/bin/ctr --help
```

Put the resulting `ctr` binary in your `$PATH`

1: Start container
```console
$ ctr images pull docker.io/library/busybox:latest
$ ctr run docker.io/library/busybox:latest boxbusy
$ ctr tasks lists
TASK PID STATUS
boxbusy 24310 RUNNING
```

2: Attach
```console
$ cntr attach boxbusy
```

It's also possible to run cntr from a container itself.
This repository contains a example Dockerfile for that:

```console
$ docker build -f Dockerfile.example . -t cntr
$ docker save cntr > cntr.tar
$ ctr images import --base-name cntr ./cntr.tar
```

In this example we attach to containerd by process id. The proccess id of a task is given in `ctr tasks list`.

```console
$ ctr run --privileged --with-ns pid:/proc/1/ns/pid --tty docker.io/library/cntr:latest cntr /usr/bin/cntr attach 31523 /bin/sh
```

To resolve containerd names one also would need to add the `ctr` binary (~12mb) to the Dockerfile.


# How it works

Cntr is container-agnostic: Instead of interfacing with container engines, it
Expand Down
2 changes: 1 addition & 1 deletion src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn parse_attach_args(args: Vec<String>) -> cntr::AttachOptions {
ap.refer(&mut container_type).add_option(
&["-t", "--type"],
Store,
"Container type (process_id|rkt|docker|nspawn|lxc|lxd|command), default: all except command)",
"Container type (process_id|rkt|docker|nspawn|lxc|lxd|command|containerd), default: all except command)",
);
ap.refer(&mut container_name).required().add_argument(
"id",
Expand Down
71 changes: 71 additions & 0 deletions src/container/containerd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use libc::pid_t;
use nix::unistd::Pid;
use std::process::Command;

use crate::cmd;
use crate::container::Container;
use crate::types::{Error, Result};

#[derive(Clone, Debug)]
pub struct Containerd {}

impl Container for Containerd {
fn lookup(&self, container_id: &str) -> Result<Pid> {
let command = format!("ctr task list");
let output = tryfmt!(
Command::new("ctr").args(&["task", "list"]).output(),
"Running '{}' failed",
command
);

if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return errfmt!(format!(
"Failed to list containers. '{}' exited with {}: {}",
command,
output.status,
stderr.trim_end()
));
}

// $ ctr task list
// TASK PID STATUS
// v2 17515 RUNNING
// v1 14602 RUNNING
let mut lines = output.stdout.split(|&c| c == b'\n');
lines.next(); // skip header
let pid_str = lines.find_map(|line| {
let line_str = String::from_utf8_lossy(&line);
let cols = line_str.split_whitespace().collect::<Vec<&str>>();
if cols.len() != 3 {
return None;
}

if cols[0] == container_id {
Some(String::from(cols[1]))
} else {
None
}
});
match pid_str {
Some(pid_str) => {
let pid = tryfmt!(
pid_str.parse::<pid_t>(),
"read invalid pid from ctr task list: '{}'",
pid_str
);
Ok(Pid::from_raw(pid))
}
None => {
errfmt!(format!("No container with id {} found", container_id))
}
}
}
fn check_required_tools(&self) -> Result<()> {
if cmd::which("ctr").is_some() {
Ok(())
} else {
errfmt!("ctr not found")
}
}
}
4 changes: 4 additions & 0 deletions src/container/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::fmt::Debug;
use crate::types::{Error, Result};

mod command;
mod containerd;
mod docker;
mod lxc;
mod lxd;
Expand All @@ -24,6 +25,7 @@ pub const AVAILABLE_CONTAINER_TYPES: &[&str] = &[
"lxc",
"lxd",
"command",
"containerd",
];

fn default_order() -> Vec<Box<dyn Container>> {
Expand All @@ -34,6 +36,7 @@ fn default_order() -> Vec<Box<dyn Container>> {
Box::new(nspawn::Nspawn {}),
Box::new(lxc::Lxc {}),
Box::new(lxd::Lxd {}),
Box::new(containerd::Containerd {}),
];
containers
.into_iter()
Expand All @@ -49,6 +52,7 @@ pub fn lookup_container_type(name: &str) -> Option<Box<dyn Container>> {
"nspawn" => Box::new(nspawn::Nspawn {}),
"lxc" => Box::new(lxc::Lxc {}),
"lxd" => Box::new(lxd::Lxd {}),
"containerd" => Box::new(containerd::Containerd {}),
"command" => Box::new(command::Command {}),
_ => return None,
})
Expand Down

0 comments on commit 9d23b59

Please sign in to comment.