Home / Alt manpages / ctr(8)

  • ctr(8)
  • Admin command
  • linux

Operate containerd Safely with ctr

By the end of this guide you will be able to inspect a containerd installation, pull an image into a namespace, create and run a task, and remove the objects you created. The examples target containerd.io 2.3.5, whose client reports ctr v2.3.5. Allow about 15 minutes if containerd is already running and you have an image registry available.

Before you start

ctr is containerd's unsupported debug and administrative client. Its commands and options can change between releases. It talks to the containerd gRPC socket, which defaults to /run/containerd/containerd.sock, and uses the default namespace unless you choose another one.

You need the containerd.io package, a running containerd daemon, and permission to access its socket. Most commands that change images, containers, or tasks need elevated privileges, either by running as the service account that owns the socket or with sudo. The examples use sudo where that is the usual arrangement.

Checkpoint: confirm the client and daemon

  1. Check the installed client version.

    ctr version

    A working connection prints both client and server version details. On this machine the client is v2.3.5. If the command reports permission denied or cannot connect to the socket, fix the service state or socket permissions before trying image operations.

  2. Inspect the plugins known to containerd.

    sudo ctr plugins ls

    Use --quiet for only plugin IDs, or --detailed when diagnosing a plugin. A command that cannot reach the daemon cannot provide useful plugin information.

Choose a namespace deliberately

Namespaces separate containerd objects. An image pulled into default is not automatically visible in another namespace. This is a frequent source of false "image not found" errors, especially when a runtime such as Kubernetes uses its own namespace.

  1. List existing namespaces.

    sudo ctr namespaces ls
  2. Create an isolated namespace for a manual test.

    sudo ctr namespaces create ctr-demo
  3. Use that namespace for each following command.

    sudo ctr --namespace ctr-demo images ls

    You can write the short form -n ctr-demo. To return to the normal namespace, omit the option or specify --namespace default.

Checkpoint: the final image list should be empty in a newly created namespace. If it is not, check that every command has the same namespace option.

Pull and inspect an image

  1. Pull a public image into the test namespace.

    sudo ctr -n ctr-demo images pull docker.io/library/alpine:3.20

    The registry transfer may take a little while. The command uses HTTPS by default. Do not add --plain-http or --skip-verify to work around a certificate problem unless you have deliberately assessed the registry and network, because those options weaken transport checks.

  2. Confirm that the image is ready.

    sudo ctr -n ctr-demo images ls
    sudo ctr -n ctr-demo images check

    images ls shows references known to the namespace. images check can restrict output to ready references with --quiet. To inspect metadata, use images inspect docker.io/library/alpine:3.20.

Create and run a short-lived task

A container is a stored definition. A task is the running process made from that definition. Creating a container does not start a process, and starting a container creates a task that must be managed separately.

  1. Create a container from the pulled image.

    sudo ctr -n ctr-demo containers create docker.io/library/alpine:3.20 ctr-demo-shell
  2. Start a task and remove the container after it exits.

    sudo ctr -n ctr-demo run --rm docker.io/library/alpine:3.20 ctr-demo-run echo 'ctr works'

    The run command combines creation and task startup. --rm removes that container when the command finishes. It cannot be combined with --detach, so use one mode or the other.

  3. Inspect the separately created container and start it interactively.

    sudo ctr -n ctr-demo tasks list
    sudo ctr -n ctr-demo tasks start --detach ctr-demo-shell
    sudo ctr -n ctr-demo tasks ps ctr-demo-shell

    The task ID is usually the container ID, but treat it as an identifier rather than assuming it. A detached task remains until you stop and delete it.

Warning: clean up in the right order

Deletion is state-changing. A task is a live process, and removing an image can affect later starts. Check the IDs before using a destructive command. Never use a broad wildcard or remove a namespace that belongs to another workload.

  1. Stop the test task by sending the default termination signal.

    sudo ctr -n ctr-demo tasks kill ctr-demo-shell
  2. Delete the task after it has stopped.

    sudo ctr -n ctr-demo tasks delete ctr-demo-shell
  3. Delete the container definition.

    sudo ctr -n ctr-demo containers delete ctr-demo-shell
  4. Remove the image, then remove the temporary namespace.

    sudo ctr -n ctr-demo images remove docker.io/library/alpine:3.20
    sudo ctr namespaces remove ctr-demo

If a task refuses to disappear, inspect it with tasks list and use tasks delete --force only when you understand why ordinary deletion failed. Forced deletion can leave the workload's process or resources in a state that needs service-level investigation.

Useful diagnostics and defaults

  • --address /path/to/containerd.sock selects a different gRPC socket. Verify the path with the service configuration before changing it.
  • --connect-timeout 10s limits the connection attempt. The default is 0s, meaning no client-side connection timeout is set.
  • --timeout 30s limits the whole command. The default is also 0s.
  • --debug enables debug output in logs. Use it for a focused reproduction, since registry tracing can expose request details.

For registry failures, first verify the image reference, namespace, DNS, and certificates. The pull command supports custom CA, client certificate, and key paths when the registry requires them. Keep credentials out of shell history where possible; --user USER:PASSWORD places them directly in the command line.

Done means

  • ctr version reaches the expected containerd daemon.
  • You can list plugins and namespaces with the privileges appropriate to the socket.
  • You know which namespace contains each image and container.
  • You can distinguish a container definition from its running task.
  • The test task, container, image, and temporary namespace are removed, or you have recorded why they remain.