Introducción a Podman
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:
- Puesto que es el primer contenedor que lanzamos con la imagen
httpd
del repositoriodocker.io
, en primer lugar se descarga la imagen en~/.local/share/containers/storage
. - 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 puerto8080/tcp
de la máquina anfitriona se dirija al puerto80/tcp
del contenedor. - 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:
- Un servidor web. Si utilizamos Apache quizás nos convenga la imagen
httpd
que se encuentra en https://hub.docker.com/_/httpd. Alternativamente se podría utilizar la imagenwordpress
que se encuentra en https://hub.docker.com/_/wordpress y ya tiene un servidor web con Wordpress. - Una base de datos. Si queremos MySQL quizás nos convenga la imagen
mysql
que se encuentra en https://hub.docker.com/_/mysql. Alternativamente se podría utilizar la imagenmariadb
que se encuentra en https://hub.docker.com/_/mariadb.
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:
- Los contenedores tienen un nombre compuesto por el directorio utilizado (
wordpress
) el nombre del servicio especificado en el fichero (db
yweb
) y un número (1
en este caso). - Se ha definido un tercer contenedor (
663f84f58792-infra
) que sirve para gestionar elpod
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: