Hi, readers this time I want to show you different tools that you can use to create containers. We are going to explore Podman, Containerd and Youki, some projects coming from CNCF. The idea of this blog post is to use the best tool for containers based on your needs, and share some basics about how to use this tools in your cloud native projects.
This blog post will focus on:
- Container Runtimes including Podman, Containerd and Youki.
What you will learn
- Container Runtime Introduction
- Containerd installation
- Create a container with the containerd Go SDK
- Install nerdctl
- Using Compose with nerdctl
- Working with Podman
- Podman Compose
- Running Containers with youki
Container Runtime Introduction
For many developers, Docker is synonymous with containers. It
provides an excellent developer experience by combining image
management, container execution, networking, and a familiar CLI into a
single tool.
However, modern Cloud Native platforms especially Kubernetes have
evolved beyond Docker as their default runtime. Today, most Kubernetes
distributions rely on containerd, while alternative tools like
Podman and nerdctl provide different ways to build and manage
containers. Underneath them all, OCI runtimes such as runc and
youki are responsible for actually creating and running containers.
Understanding how these technologies work together is an important skill
for anyone working with Kubernetes, DevOps, or Platform Engineering.
Let's summarize some container tools as follows:
- containerd: the container runtime used by most Kubernetes distributions.
- nerdctl: A Docker-compatible CLI for containerd.
- Podman: A daemonless container engine with first-class rootless support.
- youki A modern OCI runtime written in Rust.
Let's see how this tools are distributed in different abstraction layers:
Container CLI
Docker CLI | nerdctl | Podman
│
Container Engine
Docker Engine | containerd
│
OCI Runtime
runc | youki
│
Linux Kernel
Each layer has a different responsibility:
- Container Engine manages images, networking, and container lifecycle.
- OCI Runtime creates and starts Linux containers.
- CLI tools provide a user-friendly interface.
Containerd installation
Let's asume that we are using Alpine, you have to activate the community repositories in order to install containerd for this run the following steps:
1. Edit /etc/apk/repositories to uncomment the community repository
vi /etc/apk/repositories
# Uncomment the community repo for example the line will look like this
# http://dl-cdn.alpinelinux.org/alpine/v3.23/community
2. Update the repositories
apk update
3. Install containerd
apk add containerd
4. Start containerd
service containerd start
containerd --version
Create a container with the containerd Go SDK
1. Install Go in Alpine
apk add git
apk add go
2. Create a directory to create your go code
cd $HOME
mkdir containerd-example
cd containerd-example
go mod init containerd/example
3. Install Containerd libreries to compile your example
go get github.com/containerd/containerd
go get github.com/containerd/containerd/cio
go get github.com/containerd/containerd/oci
go get github.com/containerd/containerd/namespaces
4. Create the code as main.go file using the next content
package main
import (
"context"
"fmt"
"log"
"syscall"
"time"
"github.com/containerd/containerd"
"github.com/containerd/containerd/cio"
"github.com/containerd/containerd/oci"
"github.com/containerd/containerd/namespaces"
)
func main() {
if err := redisExample(); err != nil {
log.Fatal(err)
}
}
func redisExample() error {
// create a new client connected to the default socket path for containerd
client, err := containerd.New("/run/containerd/containerd.sock")
if err != nil {
return err
}
defer client.Close()
// create a new context with an "example" namespace
ctx := namespaces.WithNamespace(context.Background(), "example")
// pull the redis image from DockerHub
image, err := client.Pull(ctx, "docker.io/library/redis:alpine", containerd.WithPullUnpack)
if err != nil {
return err
}
// create a container
container, err := client.NewContainer(
ctx,
"redis-server",
containerd.WithImage(image),
containerd.WithNewSnapshot("redis-server-snapshot", image),
containerd.WithNewSpec(oci.WithImageConfig(image)),
)
if err != nil {
return err
}
defer container.Delete(ctx, containerd.WithSnapshotCleanup)
// create a task from the container
task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio))
if err != nil {
return err
}
defer task.Delete(ctx)
// make sure we wait before calling start
exitStatusC, err := task.Wait(ctx)
if err != nil {
fmt.Println(err)
}
// call start on the task to execute the redis server
if err := task.Start(ctx); err != nil {
return err
}
// sleep for a lil bit to see the logs
time.Sleep(3 * time.Second)
// kill the process and get the exit status
if err := task.Kill(ctx, syscall.SIGTERM); err != nil {
return err
}
// wait for the process to fully exit and print out the exit status
status := <-exitStatusC
code, _, err := status.Result()
if err != nil {
return err
}
fmt.Printf("redis-server exited with status: %d\n", code)
return nil
}
Install nerdctl
1. Install nerdctl to use containerd
apk add nerdctl
nerdctl --version
2. Use nerdctl to create a container
nerdctl run -d nginx
Using Compose with nerdctl
nerdctl compose up -d
nerdctl compose ps
nerdctl compose logs -f
nerdctl compose build
nerdctl compose down
Working with Podman
1. Install Podman
apk add podman
2. Create a container using Podman
podman run -it -d redis
3. List containers with Podman
podman ps
Podman Compose
podman compose up -d
podman compose ps
podman compose logs -f
podman compose down
Running Containers with youki
1. Install youki dependencies
apk add libseccomp curl
curl -sSfL https://github.com/youki-dev/youki/releases/download/v0.6.0/youki-0.6.0-$(uname -m)-musl.tar.gz | tar -xzvC /usr/bin/ youki
youki --version # Test youki installation
2. List containers created by youki
podman run --runtime /usr/bin/youki -d -p 8080:80 nginx
youki list
Conclusion about Container Runtimes
The Cloud Native ecosystem has become increasingly modular.
Understanding how containerd, nerdctl, Podman, and youki
work together helps you better understand how modern container
platforms and Kubernetes itself run workloads in production.
Thanks for reading! Last to say, see you in my next blog post.
Follow me
These are my social networks:
https://www.linkedin.com/in/sergioarmgpl
https://sergiops.xyz
https://x.com/sergioarmgpl
https://www.instagram.com/sergioarmgpl/
Please contribute to these awesome projects:
Top comments (0)