microk8s
containerd
image pruning
kubernetes
docker alternatives

How to make microk8s ctr image prune

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

MicroK8s uses containerd under the hood, and ctr is the low-level client for inspecting that runtime. The important detail is that ctr is not Docker, so you usually do not get a single friendly image prune command that safely cleans everything up for you.

Why ctr cleanup works differently

In a MicroK8s setup, images are commonly stored in the k8s.io namespace because Kubernetes workloads live there. If you run ctr without the right namespace, you may think the image store is empty or accidentally inspect the wrong data.

The second difference is conceptual. Containerd tracks content, snapshots, containers, and image references separately. Deleting an image reference is not the same thing as blindly deleting every blob on disk. That is why a safe cleanup flow starts by identifying what Kubernetes is still using, then removing only images you no longer want cached.

A practical prune workflow

The following sequence is a safe manual equivalent of "prune unused images." It lists stored images, lists images referenced by running workloads, and removes an image explicitly.

bash
1microk8s ctr --namespace k8s.io images ls
2
3microk8s kubectl get pods -A -o jsonpath='{..image}' | xargs -n1 | sort -u
4
5microk8s ctr --namespace k8s.io images rm docker.io/library/nginx:1.25

The first command shows what containerd currently knows about. The second command shows what your cluster is actively configured to use. Compare the two lists before deleting anything. If an image still appears in a Deployment, DaemonSet, Job, or CronJob, the cluster may need it again even if no pod is running at this moment.

What "prune" should mean in MicroK8s

A good prune policy in MicroK8s is conservative:

  • Remove images that are clearly old tags, failed experiments, or one-off test pulls.
  • Keep images for workloads you expect to restart soon.
  • Prefer explicit deletion over mass removal unless the node is disposable.

This matters because Kubernetes is constantly reconciling state. If you remove an image that a controller still expects, the next pod start will trigger a new pull. That may be acceptable, but it should be a deliberate choice, not an accident caused by treating ctr like Docker.

Checking what is safe to delete

Beyond running pods, review your manifests and controllers. A stopped Job, a scaled-to-zero Deployment, or a Helm release you plan to re-enable can still depend on an image that no current pod references. On small developer machines, a useful rule is to delete only images whose tag you recognize as obsolete and whose workload has been removed from the cluster configuration.

If you are doing frequent local experiments, it is often better to pin fewer tags and rebuild or import consistently than to let many near-identical images accumulate.

When to use a higher-level tool

ctr is powerful, but it is intentionally low level. If your goal is everyday cluster administration rather than containerd internals, a Kubernetes-aware or CRI-aware tool may be easier to reason about. Even then, the same principle applies: inspect first, delete second, and remember that the runtime cache and the declarative cluster state are related but not identical.

Common Pitfalls

  • Forgetting the k8s.io namespace and concluding that MicroK8s has no images.
  • Expecting a Docker-style one-command prune workflow from ctr.
  • Deleting an image still referenced by a Deployment or Job and being surprised when it is pulled again.
  • Confusing image references with all runtime data on disk. Removing one does not mean every related artifact disappears instantly.
  • Running cleanup on a node that is short-lived only during development, then spending more time re-pulling images than you saved.

Summary

  • In MicroK8s, image cleanup with ctr is usually an explicit delete workflow, not a single prune command.
  • Always inspect the k8s.io namespace because that is where Kubernetes images normally live.
  • Compare stored images with the images referenced by cluster workloads before removing anything.
  • Delete obsolete tags deliberately rather than trying to wipe the cache blindly.
  • Treat ctr as a low-level containerd tool, not as a drop-in replacement for Docker CLI behavior.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.