Introducción a Podman

per Victor Carceler darrera modificació 2021-06-28T10:49:33+01:00

podman.webp

Podman es una herramienta libre que permite desarrollar, gestionar y ejecutar contenedores. Utiliza los mismos parámetros que docker, así que si acostumbras a utilizar esta última herramienta y quieres probar podman será suficiente con que definas el siguiente alias:

alias docker=podman

Y sigas trabajando como lo hacías antes.

Pero si sigues leyendo descubrirás que podman, a diferencia de docker, no ejecuta ningún demonio en el sistema. Y está disponible tanto para el usuario root como para usuarios no privilegiados.

Si nunca has trabajado con podman, o con docker, aquí encontrarás una pequeña introducción a este tipo de contenedores.

¿Qué son los contenedores?

Los contenedores son una alternativa a las máquinas virtuales. Utilizan virtualización a nivel de sistema operativo y no recrean ni un hardware ni un núcleo diferente del que se encuentra en la máquina que los alberga. Por lo tanto consumen menos recursos que las máquinas virtuales, permiten mayores densidades y el software que se ejecuta en el contenedor obtiene el mismo rendimiento que los procesos nativos de  la máquina física.

Existen diferentes herramientas para ejecutar contenedores en GNU/Linux. Algunas de ellas, como LXD/LXC, recrean contenedores de sistema con lo que parece una máquina ejecutando una distribución de GNU/LInux. Otras herramientas, como podman o docker, están enfocadas a contenedores mínimos que únicamente ejecutan un servicio: un servidor web, una base de datos, un servidor de correo...

En este último caso para desplegar una aplicación real suelen ser necesarios varios contenedores que interactúan entre sí.

De acuerdo, quiero ejecutar un contenedor con podman

Pues gracias a los repositorios de imágenes preparadas es muy sencillo. Por ejemplo, para lanzar un contenedor con un servidor web Apache a partir de la imagen docker.io/library/httpd se puede ejecutar:

[vcarceler@alumne-1-58 ~]$ podman run -dt -p 8080:80/tcp docker.io/library/httpd
Trying to pull docker.io/library/httpd:latest...
Getting image source signatures
Copying blob 4b72f5187e6e done
Copying blob b4d181a07f80 done
Copying blob 12b2c44d04b2 done
Copying blob ef481fc2a03a done
Copying blob d483d945fcab done
Copying config 30287d8996 done
Writing manifest to image destination
Storing signatures
7cd3f783d1bf8ccde7b990bf7880ddedc2954f10aced252926f824df4e22e812
[vcarceler@alumne-1-58 ~]$

Al ejecutar el comando suceden varias cosas:

  1. Puesto que es el primer contenedor que lanzamos con la imagen httpd del repositorio docker.io, en primer lugar se descarga la imagen en ~/.local/share/containers/storage.
  2. Se crea un nuevo contenedor a partir de la imagen indicada. El parámetro -p 8080:80/tcp hará que todo el tráfico que llegue al puerto 8080/tcp de la máquina anfitriona se dirija al puerto 80/tcp del contenedor.
  3. Se ejecuta el nuevo contenedor en segundo plano gracias al parámetro -dt. Una vez que el contenedor está en ejecución se retorna su identificador: 7cd3f783d1bf8ccde7b990bf7880ddedc2954f10aced252926f824df4e22e812.

Desde este momento se podrá abrir un navegador para hacer una petición a alguna de las direcciones de la máquina anfitriona en el puerto 8080, por ejemplo 127.0.0.1:8080, y comprobar que responde el servidor web Apache que se encuentra en el contenedor.

Resulta interesante comprobar que el comando podman ps nos mostrará los contenedores en ejecución (con -a se mostrarán también los contenedores detenidos)

[vcarceler@alumne-1-58 ~]$ podman ps 
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7cd3f783d1bf docker.io/library/httpd:latest httpd-foreground 16 minutes ago Up 16 minutes ago 0.0.0.0:8080->80/tcp xenodochial_newton
[vcarceler@alumne-1-58 ~]$

Los contenedores se pueden detener y encender con los comando podman stop y podman start bien indicando su nombre, xenodochial_newton en este caso, o su ID. Cuando no se necesite más el contenedor se puede eliminar con el comando podman rm.

También se puede mostrar información sobre las imágenes descargadas con el comando:

vcarceler@alumne-1-58 ~]$ podman image list
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/httpd latest 30287d899656 2 days ago 142 MB
[vcarceler@alumne-1-58 ~]$

Volúmenes para guardar los datos de trabajo

La imagen de los contenedores incluye lo mínimo necesario para ejecutar el servicio, Apache en este caso, pero no proporciona almacenamiento persistente para la aplicación. Es decir, para publicar una página web será necesario contar con un espacio de almacenamiento para guardar sus contenidos.

Los volúmenes permiten definir un directorio de la máquina anfitriona que en el interior del contendor se verá montado en el lugar que indiquemos.

En nuestro caso el servidor web Apache que se encuentra en la imagen utilizada espera encontrar los contenidos de la web en /usr/local/apache2/htdocs.

Podemos definir un nuevo volumen para guardar la web

[vcarceler@alumne-1-58 ~]$ podman volume create www
www

Y crear nuestro contenedor indicando que se debe utilizar el volumen www montado en el directorio que Apache tiene configurado como raíz de los contenidos.

[vcarceler@alumne-1-58 ~]$ podman run -dt --name apache -p 8080:80 -v www:/usr/local/apache2/htdocs docker.io/library/httpd
709dc10fc7e6e6867ddae8e038546eee1f6eececc28976f1c94c9a4b82f83116

Si inspeccionamos el volumen www descubriremos que el directorio de la máquina anfitriona en el que hay que dejar la web para que la publique el contenedor es /home/vcarceler/.local/share/containers/storage/volumes/www/_data

[vcarceler@alumne-1-58 ~]$ podman volume inspect www 
[
{
"Name": "www",
"Driver": "local",
"Mountpoint": "/home/vcarceler/.local/share/containers/storage/volumes/www/_data",
"CreatedAt": "2021-06-25T22:45:06.241452394+02:00",
"Labels": {},
"Scope": "local",
"Options": {}
}
]

Conjuntos de contenedores con podman-compose

Si cada contenedor ejecuta un servicio diferente puede ocurrir que hasta para implementar una pequeña aplicación se necesiten varios contenedores. Por ejemplo, un blog Wordpress precisará dos contenedores:

Estos contenedores deberán comunicarse entre sí y muy probablemente necesiten sus propios volúmenes para guardar datos.

Aunque es posible utilizar el comando podman para definir de la manera adecuada cada uno de los contenedores, se trata de un trabajo tedioso que puede ser automatizado con la herramienta podman-compose que funciona como lo hace docker-compose.

Estas herramientas pueden definir los contenedores necesarios para una aplicación a partir de un fichero docker-compose.yaml.

Para ponerlo a prueba podemos crear el directorio wordpress con el siguiente fichero docker-compose.yaml en su interior.

version: "3.8"
services: 
  web:
    image: docker.io/library/wordpress
    restart: always
    volumes:
      - wordpress:/var/www/html
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: magazine
      WORDPRESS_DB_NAME: magazine
      WORDPRESS_DB_PASSWORD: 1maGazine!
      WORDPRESS_TABLE_PREFIX: cz
      WORDPRESS_DEBUG: 0
    depends_on:
      - db
    networks:
      - wpnet
  db:
    image: docker.io/library/mariadb:10.5
    restart: always
    ports:
      - 6603:3306

    volumes:
      - wpdbvol:/var/lib/mysql

    environment:
      MYSQL_DATABASE: magazine
      MYSQL_USER: magazine
      MYSQL_PASSWORD: 1maGazine!
      MYSQL_ROOT_PASSWORD: 1maGazine!
    networks:
      - wpnet
volumes:
  wordpress: {}
  wpdbvol: {}

networks:
  wpnet: {}

Al acceder al directorio y ejecutar podman-compose up se iniciará el proceso que ejecutará dos nuevos contenedores: wordpress_db_1 y wordpress_web_1. Por supuesto estarán configuradas las redirecciones de puertos y los volúmenes especificados.

[vcarceler@alumne-1-58 wordpress]$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
90868f67e1f7 k8s.gcr.io/pause:3.5 19 minutes ago Up 18 minutes ago 0.0.0.0:8080->80/tcp, 0.0.0.0:6603->3306/tcp 663f84f58792-infra
6b2f96b56b5c docker.io/library/mariadb:10.5 mysqld 19 minutes ago Up 18 minutes ago 0.0.0.0:8080->80/tcp, 0.0.0.0:6603->3306/tcp wordpress_db_1
118a5c67c57d docker.io/library/wordpress:latest apache2-foregroun... 19 minutes ago Up 18 minutes ago 0.0.0.0:8080->80/tcp, 0.0.0.0:6603->3306/tcp wordpress_web_1
[vcarceler@alumne-1-58 wordpress]$

Al acceder a http://127.0.0.1:8080 se encontrará un Wordpress recién instalado listo para su configuración inicial.

Como se puede ver en el listado anterior:

  1. Los contenedores tienen un nombre compuesto por el directorio utilizado (wordpress) el nombre del servicio especificado en el fichero (db y web) y un número (1 en este caso).
  2. Se ha definido un tercer contenedor (663f84f58792-infra) que sirve para gestionar el pod en el que se encuentran nuestros dos contenedores.

Un pod es un grupo de contenedores que comparten recursos y que se pueden comunicar directamente entre sí. En nuestro caso podemos listar los pods disponibles:

[vcarceler@alumne-1-58 wordpress]$ podman pod ls
POD ID        NAME       STATUS   CREATED         INFRA ID      # OF CONTAINERS
663f84f58792  wordpress  Running  24 minutes ago  90868f67e1f7  3
[vcarceler@alumne-1-58 wordpress]$ 

Y detener o volver a encender todos los contenedores de un pod con los comandos podman pod stop y podman pod start.

Al comprobar los volúmenes se encontrarán los dos volúmenes que proporcionan espacio de almacenamiento al servidor web y a la base de datos.

[vcarceler@alumne-1-58 wordpress]$ podman volume ls
DRIVER VOLUME NAME
local wordpress_wordpress
local wordpress_wpdbvol
[vcarceler@alumne-1-58 wordpress]$

Naturalmente también encontraremos las imágenes utilizadas:

[vcarceler@alumne-1-58 wordpress]$ podman image ls
REPOSITORY                   TAG     IMAGE ID      CREATED       SIZE
docker.io/library/mariadb    10.5    6d5c5ed114ad  2 days ago    414 MB
docker.io/library/wordpress  latest  47a09363748b  2 days ago    563 MB
k8s.gcr.io/pause             3.5     ed210e3e4a5b  3 months ago  690 kB
[vcarceler@alumne-1-58 wordpress]$ 

Enlaces: