Ir al contenido

Container Runtimes para proyectos Cloud Native

30 de junio de 2026 por
Container Runtimes para proyectos Cloud Native
Sergio Méndez

Container Runtimes para proyectos Cloud Native

Hola, lectores. En esta ocasión quiero mostrarles diferentes herramientas que pueden usar para crear contenedores. Exploraremos Podman, Containerd y Youki, algunos proyectos de la CNCF. El objetivo de esta publicación es ayudarles a elegir la mejor herramienta para contenedores según sus necesidades y compartir algunos conceptos básicos sobre cómo usar estas herramientas en sus proyectos nativos de la nube.

Esta publicación se centrará en:

  • Entornos de ejecución de contenedores, incluyendo Podman, Containerd y Youki.
Lo que aprenderás
  • Introducción a Container Runtimes
  • Instalación de Containerd
  • Creación de un contenedor con el SDK de Go para containerd
  • Instalación de nerdctl
  • Uso de Compose con nerdctl
  • Trabajo con Podman
  • Podman Compose
  • Ejecución de contenedores con youki

Introducción a Container Runtimes

Para muchos desarrolladores, Docker es sinónimo de contenedores. Ofrece una excelente experiencia de desarrollo al combinar la gestión de imágenes, la ejecución de contenedores, la conectividad en red y una interfaz de línea de comandos familiar en una sola herramienta.

Sin embargo, las plataformas modernas nativas de la nube, especialmente Kubernetes, han evolucionado más allá de Docker como su entorno de ejecución predeterminado. Hoy en día, la mayoría de las distribuciones de Kubernetes dependen de containerd, mientras que herramientas alternativas como Podman y nerdctl ofrecen diferentes maneras de crear y administrar contenedores. Detrás de todas ellas, los entornos de ejecución de OCI, como runc y youki, son los responsables de crear y ejecutar los contenedores.

Comprender cómo funcionan estas tecnologías en conjunto es una habilidad importante para cualquier persona que trabaje con Kubernetes, DevOps o ingeniería de plataformas.

A continuación, resumimos algunas herramientas para contenedores:

  • containerd: el entorno de ejecución de contenedores utilizado por la mayoría de las distribuciones de Kubernetes.
  • nerdctl: una interfaz de línea de comandos compatible con Docker para containerd.
  • Podman: un motor de contenedores sin demonio con soporte de primera clase para usuarios sin privilegios de administrador.
  • youki: un entorno de ejecución OCI moderno escrito en Rust.

Veamos cómo se distribuyen estas herramientas en diferentes capas de abstracción:

           Container CLI
      Docker CLI | nerdctl | Podman
                 │
          Container Engine
   Docker Engine | containerd
                 │
             OCI Runtime
            runc | youki
                 │
            Linux Kernel

Cada capa tiene una responsabilidad diferente:

  • Container Engine: gestiona las imágenes, la red y el ciclo de vida de los contenedores.
  • OCI Runtime: crea e inicia contenedores Linux.
  • Container CLI: Las herramientas de línea de comandos proporcionan una interfaz fácil de usar.

Instalación de Containerd

Supongamos que estamos usando Alpine, tienes que activar los repositorios de la comunidad para poder instalar containerd. Para ello, sigue los siguientes pasos:

1. Edita /etc/apk/repositories para descomentar el repositorio de la comunidad

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. Actualiza los repositorios

apk update

3. Instala containerd

apk add containerd

4. Inicia containerd

service containerd start
containerd --version

Create a container with the containerd Go SDK

1. Instala Go en Alpine

apk add git
apk add go

2. Crea un directorio para crear el código de Go

cd $HOME
mkdir containerd-example
cd containerd-example
go mod init containerd/example

3. Instala las librerías de Containerd para compilar el ejemplo

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. Crea el código en un archivo llamado main.go usando el siguiente contenido

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
}

Instala nerdctl

1. Instala nerdctl para usar containerd

apk add nerdctl
nerdctl --version

2. Usa nerdctl para crear un container de nginx

nerdctl run -d nginx

Usando Compose con nerdctl

nerdctl compose up -d
nerdctl compose ps
nerdctl compose logs -f
nerdctl compose build
nerdctl compose down

Trabajand con Podman

1. Instala Podman

apk add podman

2. Crea un container de Redis usando Podman

podman run -it -d redis

3. Lista los container creados con Podman

podman ps

Podman Compose

podman compose up -d
podman compose ps
podman compose logs -f
podman compose down

Corriendo Containers con youki

1. Instala las dependencias de youki

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. Lista containers creados con youki (En este caso con podman)

podman run --runtime /usr/bin/youki -d -p 8080:80 nginx
youki list

Conclusión sobre Container Runtimes

El ecosistema nativo de la nube se ha vuelto cada vez más modular. Comprender cómo funcionan containerd, nerdctl, Podman y youki en conjunto te ayuda a entender mejor cómo las plataformas de contenedores modernas y Kubernetes ejecutan cargas de trabajo en producción.

¡Gracias por leer! Nos vemos en mi próxima publicación del blog.

Sígueme

Estas son mis redes sociales:

Contribuye a estos proyectos:

K3d & K3s para ambientes Kubernetes locales