containerd Namespaces

containerd namespaces provide resource isolation for multi-tenancy. Learn how Docker uses the 'moby' namespace, Kubernetes uses 'k8s.io', and how to create your own isolated environments.

Namespace Isolation moby k8s.io Multi-tenancy
What are containerd Namespaces?

Namespaces in containerd are a way to isolate resources within a single containerd daemon. They provide logical separation of containers, images, snapshots, and other resources. Different namespaces are completely independent — containers in one namespace cannot see containers in another namespace.

This is different from Linux kernel namespaces (which isolate processes). containerd namespaces are a higher-level concept for resource organization and multi-tenancy.

containerd Daemon
moby
(Docker)
k8s.io
(Kubernetes)
mytenant
(Custom)
containers
images
snapshots
containers
images
snapshots
containers
images
snapshots
Namespaces allow a single containerd instance to serve multiple orchestrators (Docker and Kubernetes) simultaneously without resource conflicts.
Default Namespaces: moby and k8s.io

moby

Used by Docker Engine. When you run `docker run`, containers are created in the `moby` namespace. Docker Desktop also uses this namespace.

k8s.io

Used by Kubernetes. All pods and containers managed by kubelet run in the `k8s.io` namespace. This isolates Kubernetes workloads from Docker containers.

default (ctr)

The `ctr` CLI uses a namespace called `default` when no namespace is specified. This is separate from Docker and Kubernetes.

# List all namespaces ctr namespace ls # Output example: NAME LABELS moby k8s.io default
Docker and the 'moby' Namespace

When you run Docker commands, Docker Engine uses the `moby` namespace. This isolates Docker containers from other containerd users.

# Run a Docker container docker run -d --name nginx nginx:alpine # View Docker containers from containerd perspective ctr -n moby container ls ctr -n moby task ls # View images pulled by Docker ctr -n moby image ls # Inspect Docker container details ctr -n moby container info nginx # Note: Container names in containerd may differ from Docker names
Docker Engine and containerd communicate via the `moby` namespace. Your `docker run` commands create resources in this namespace.
Kubernetes and the 'k8s.io' Namespace

Kubernetes uses the `k8s.io` namespace for all container operations. This allows K8s to run alongside Docker without interference.

# On a Kubernetes node, list pods from containerd ctr -n k8s.io container ls # List all containers (including pause containers) ctr -n k8s.io container ls -q # View images cached for Kubernetes ctr -n k8s.io image ls # Inspect a pod's pause container ctr -n k8s.io container info k8s.gcr.io/pause:3.9 # Use crictl for Kubernetes-specific commands (easier) crictl pods crictl ps
Never manually modify containers in the `k8s.io` namespace unless you understand Kubernetes internals. This can break cluster functionality.
Creating Custom Namespaces
# Create a new namespace ctr namespace create myapp-prod ctr namespace create myapp-staging ctr namespace create myapp-dev # List namespaces to verify ctr namespace ls # Create a namespace with labels ctr namespace create --label environment=production myapp-prod ctr namespace create --label team=backend backend-team # Describe a namespace ctr namespace ls -l # Delete a namespace (removes all resources inside) ctr namespace rm myapp-dev
Working Within Namespaces
# Pull image into specific namespace ctr -n myapp-prod image pull docker.io/library/nginx:alpine # List images in namespace ctr -n myapp-prod image ls # Run container in namespace ctr -n myapp-prod run --rm docker.io/library/nginx:alpine test echo "Hello" # List containers in namespace ctr -n myapp-prod container ls # Run interactive shell in namespace ctr -n myapp-prod run --rm -t docker.io/library/alpine:latest test sh # Set default namespace for ctr (via environment) export CONTAINERD_NAMESPACE=myapp-prod ctr image ls # now uses myapp-prod
Multi-tenancy Example: Isolated Environments

This example shows how to create isolated environments for different teams or applications.

# Create namespaces for different teams ctr namespace create team-alpha ctr namespace create team-beta ctr namespace create team-gamma # Team Alpha deploys their app ctr -n team-alpha image pull docker.io/library/nginx:alpine ctr -n team-alpha run -d docker.io/library/nginx:alpine alpha-web # Team Beta deploys their app (same image name, no conflict) ctr -n team-beta image pull docker.io/library/nginx:alpine ctr -n team-beta run -d docker.io/library/nginx:alpine beta-web # Team Gamma runs different image ctr -n team-gamma image pull docker.io/library/redis:alpine ctr -n team-gamma run -d docker.io/library/redis:alpine gamma-cache # Verify isolation - containers only visible within their namespace ctr -n team-alpha container ls ctr -n team-beta container ls ctr -n team-gamma container ls # Namespaces are completely isolated - no resource sharing by default
Namespace Persistence and Storage

Namespaces and their resources persist across containerd restarts. Storage is isolated per namespace.

# Check storage location (Linux) ls /var/lib/containerd/io.containerd.content.v1.content/ ls /var/lib/containerd/io.containerd.metadata.v1.bolt/meta.db # Each namespace's metadata is stored in the same BoltDB database # But entries are keyed by namespace # Namespace labels can be viewed ctr namespace ls -l # Add labels to existing namespace ctr namespace label myapp-prod environment=production ctr namespace label myapp-prod owner=platform-team
Debugging with Namespaces
# Find which namespace a container belongs to # First, list all containers across all namespaces for ns in $(ctr namespace ls -q); do echo "=== Namespace: $ns ===" ctr -n $ns container ls done # Check Docker containers via containerd ctr -n moby container ls # Check Kubernetes containers ctr -n k8s.io container ls # Check if a specific image exists across namespaces for ns in $(ctr namespace ls -q); do if ctr -n $ns image ls | grep -q nginx; then echo "Found nginx in namespace: $ns" fi done
containerd Namespaces vs Linux Namespaces
  • containerd Namespaces: Logical separation within the containerd daemon for resource organization (images, containers, snapshots). Higher-level, API-level isolation.
  • Linux Namespaces: Kernel-level isolation for processes (PID, NET, MNT, UTS, IPC, USER, CGROUP). Used by containers for process isolation.
containerd namespaces complement Linux namespaces. They add an extra layer of organization and multi-tenancy on top of kernel isolation.
Frequently Asked Questions
Can a container access resources from another namespace?
No. Namespaces provide strict isolation. A container in one namespace cannot see or interact with containers, images, or snapshots in another namespace. This is a logical boundary within containerd.
Does removing a namespace delete all its resources?
Yes! When you run `ctr namespace rm `, ALL containers, images, snapshots, and other resources in that namespace are permanently deleted. Use with caution.
Why does Docker use 'moby' namespace?
Docker Engine uses 'moby' to isolate its containers from other containerd users. This allows containerd to serve multiple orchestrators (Docker, Kubernetes, custom) simultaneously.
Can I see Kubernetes pods using containerd commands?
Yes! Use `ctr -n k8s.io container ls` to see all containers on a Kubernetes node. Use `crictl ps` for a more user-friendly view.
How many namespaces can containerd handle?
There's no hard limit. You can create hundreds of namespaces. Each namespace adds minimal overhead (metadata storage).
Can I set a default namespace for ctr?
Yes! Set the environment variable `CONTAINERD_NAMESPACE=your-namespace`. Then `ctr` commands will use that namespace automatically.
Do containers in different namespaces share the same network?
Network isolation depends on the network configuration. By default, containers in different namespaces can still communicate via host networking. For network isolation, you need CNI plugins or network namespaces.
How do I migrate resources between namespaces?
There's no built-in migration. You need to export images (`ctr image export`), save them, and import into the target namespace. Containers must be recreated.
Previous: containerd Architecture Next: Snapshot Drivers

Namespaces are a powerful feature for multi-tenancy in containerd. Use them to isolate workloads, separate environments, and organize resources efficiently.