- Nextย lessonย โ
- nerdctl: Evaluating containerd as a Potential Docker Alternative
ctr: Using containerd with the Default Command-Line Client
ctr is a command-line client shipped as part of the containerd project.
If you have containerd running on a machine, chances are the ctr
binary is also present there.
๐งโ๐ In this lesson, the playground is a regular Linux server with pre-installed Docker. Since Docker is built on top of containerd, ctr
is also available in the playground - try running ctr version
in the online terminal on the right.
The ctr
client is similar to Docker's eponymous CLI, but the commands and flags often differ from their (typically more user-friendly) docker
analogs.
Historically, the primary audience of the ctr
client was containerd developers themselves testing the daemon.
However, ctr
can serve as a great exploration means - it operates right on top of the containerd API, and by examining the available commands, you can get a rough idea of what containerd can or cannot do.
ctr
is also well-suitable for learning about the capabilities of low-level OCI container runtimes since the ctr + containerd
bundle sits much closer to actual containers than docker + dockerd
.
Basic image management with ctr
Pulling images with ctr
always requires a fully-qualified reference - in other words, you cannot omit the domain or the tag parts (the digest doesn't have to be provided, though).
Try the following command to pull the latest nginx
image from Docker Hub:
ctr images pull docker.io/library/nginx:latest
Start the playground to activate solution checking.
You can list local images using the following ctr
command:
ctr images ls
As we'll see in the next lesson, containerd is often used by higher-level tools to build container images.
However, containerd doesn't provide out-of-the-box image building support, so there's no ctr images build
command.
Luckily, you can load existing images into containerd using the ctr images import
command.
Here is how you can build an image with docker build
(or any other OCI-compatible image builder) and then import it:
docker build -t iximiuz/test -f - . <<EOF
FROM busybox:latest
CMD echo just a test
EOF
docker save -o iximiuz-test.tar iximiuz/test
ctr images import iximiuz-test.tar
Start the playground to activate solution checking.
Much like in Docker, you can tag local images with the ctr images tag
command. For instance:
ctr images tag docker.io/iximiuz/test:latest localhost:5000/iximiuz/test:latest
Start the playground to activate solution checking.
Now you can push the image to a local registry - the playground already has one running on port 5000
:
ctr images push localhost:5000/iximiuz/test:latest
Start the playground to activate solution checking.
To remove the image, use the ctr images remove
command:
ctr images remove localhost:5000/iximiuz/test:latest
Start the playground to activate solution checking.
Advanced image management with ctr
Sometimes, you may want to inspect the internal structure of an image. With ctr
, you can do it using the ctr images export
command that saves the image's rootfs to a tarball:
ctr images export /tmp/nginx.tar docker.io/library/nginx:latest
Start the playground to activate solution checking.
When dealing with image layers is not desirable, you can mount an image to a temporary directory on the host and explore its contents as a regular filesystem:
mkdir /tmp/nginx
ctr images mount docker.io/library/nginx:latest /tmp/nginx
Start the playground to activate solution checking.
The file contents of the Nginx image should appear under /tmp/nginx
. Try:
ls -l /tmp/nginx/
The result will look like a typical Linux filesystem, and it's not surprising since the Nginx image is based on the Debian Linux distribution:
total 84
drwxr-xr-x 2 root root 4096 May 2 00:00 bin
drwxr-xr-x 2 root root 4096 Apr 2 11:55 boot
drwxr-xr-x 2 root root 4096 May 2 00:00 dev
drwxr-xr-x 1 root root 4096 May 3 19:51 docker-entrypoint.d
-rwxrwxr-x 1 root root 1616 May 3 19:50 docker-entrypoint.sh
drwxr-xr-x 1 root root 4096 May 3 19:51 etc
...
Don't forget to unmount the image when you're done with it ๐
ctr images unmount /tmp/nginx
Start the playground to activate solution checking.
Basic container management with ctr
Having a local image, you can run a container with ctr run <image-ref> <container-id>
.
For instance, here is how you can run a docker.io/iximiuz/test:latest
container from the image we've imported earlier:
ctr run -t docker.io/iximiuz/test:latest test1
Start the playground to activate solution checking.
Notice that unlike user-friendly docker run
that generates a unique container ID for you, with ctr
, you must supply the unique container ID yourself.
The ctr run
command supports only the most basic flags: --env
, -t,--tty
, -d,--detach
, --rm
, etc.
But no port publishing or automatic container restart with --restart=always
- these are not supported by containerd out of the box.
Similarly to images, you can list existing containers with:
ctr containers ls
You can also inspect a container with ctr containers info <container-id>
:
ctr containers info test1
Finally, you can remove a container with ctr containers remove <container-id>
:
ctr containers remove test1
Start the playground to activate solution checking.
Hi there! ๐ I'm Ivan, the author of this course and the founder of iximiuz Labs.
If you've found this platform helpful on your learning journey, please consider supporting its development on Patreon. As a patron, not only will you have my heartfelt thanks, but you'll also enjoy some nice perks!
Advanced container management with ctr
Interesting that the ctr run
command is actually a shortcut for ctr container create
followed by ctr task start
.
Let's explore this behavior:
ctr container create -t docker.io/library/nginx:latest nginx1
Start the playground to activate solution checking.
Let's list the created containers:
ctr container ls
CONTAINER IMAGE RUNTIME
...
nginx1 docker.io/library/nginx:latest io.containerd.runc.v2
...and check the running processes:
pgrep nginx
<empty>
As you can see, the container is created but not running.
To make the Nginx container actually run, you'll need to start a task:
ctr task start -d nginx1 # -d for --detach
Start the playground to activate solution checking.
You can list the running tasks with the following command:
ctr task ls
The output should be similar to the following:
TASK PID STATUS
nginx1 39928 RUNNING
๐ค I like this separation of container
and task
subcommands because it reflects the often forgotten nature of OCI containers.
Despite the common belief, containers aren't processes - containers are isolated and restricted execution environments for processes.
To see the stdout/stderr of the running task, you can attach to it with ctr task attach <task-id>
.
But be careful, this command will reconnect all stdio streams of the task to your terminal, so hitting Ctrl+C
will kill the task:
ctr task attach nginx1
The output will be similar to the following:
...
2023/05/06 18:48:22 [notice] 1#1: using the "epoll" event method
2023/05/06 18:48:22 [notice] 1#1: nginx/1.23.4
2023/05/06 18:48:22 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2023/05/06 18:48:22 [notice] 1#1: OS: Linux 5.10.175
2023/05/06 18:48:22 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1024:1024
2023/05/06 18:48:22 [notice] 1#1: start worker processes
2023/05/06 18:48:22 [notice] 1#1: start worker process 29
...
Much like in Docker, you can execute a task in an existing container.
Open another terminal tab on the right and run the following command to get an interactive shell inside the nginx1
container:
ctr task exec -t --exec-id bash1 nginx1 bash
Or you can execute a single command inside the container without getting an interactive shell. For instance, here's how you can curl the Nginx container from the host (you may need another terminal tab for this):
ctr task exec --exec-id curl1 nginx1 curl 127.0.0.1:80
The output will be the standard Nginx welcome page:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
...
Before removing a container, all its tasks must be stopped:
ctr task kill -s 9 nginx1
Alternatively, you can remove running tasks using the --force
flag:
ctr task rm -f nginx1
Start the playground to activate solution checking.
Summary
In this lesson, you've learned how to use the ctr
command to manage containerd images and containers.
One of the key takeaways should probably be that it's doable but not very convenient.
As a lower-level container runtime, containerd doesn't provide such familiar to Docker users featurer as
image building, port publishing, or automatic container restart on failure.
In the next lesson, we'll see how to use the nerdctl
command-line client to manage deal with containers and images in a much more user-friendly way.