Este es uno de los capítulos del tutorial Tutorial de Podman. Encontrarás los enlaces a todos los de capítulos, al final de este artículo.
A estas alturas, ya sabes que es Podman. Has visto que tiene determinadas características que lo hace realmente interesante. Como ya te imaginabas, has podido constatar que la instalación de Podman es realmente sencilla, aunque necesitas algunos pasos para dejarlo fino, pero nada realmente complicado. Y por supuesto, te puede el ansía y necesitas comenzar a utilizarlo, prácticamente para cualquier cosa. Sin embargo, te voy a dar un noticia regulera, algo que te adelanté en el capítulo anterior del tutorial. Tienes que conocer como gestionar imágenes con Podman.
Gestionar imágenes con Podman, es algo que tienes que tener muy de la mano, algo a lo que te tienes que acostumbrar. Y no solo se trata de descargar imágenes de diferentes repositorios, sino también se trata de gestionar imágenes, actualizar aquellas imágenes que ya están desactualizadas o incluso borrar esas imágenes que ya has dejado de utilizar. Así que, vamos allá a gestionar imágenes con Podman.
Gestionar imágenes con Podman
Un breve recordatorio
Antes que nada, una pequeña introducción o recordatorio. ¿Que es una imagen? Una imagen no es ni mas ni menos que una aplicación o servicio empaquetado con todo aquello que necesitas para su correcto funcionamiento, todas las dependencias necesarias.
Esto desde el punto de vista del usuario, porque cuando comiences a construir tus propias imágenes, verás que se parecen, tremendamente, a una receta.
Pero, ¿donde están esas imágenes?
Registries, el lugar de las imágenes
Las imágenes están guardadas en Registries. Por defecto, al instalar Podman, se configuran dos Registries en tu equipo, docker.io
y quay.io
, pero puedes añadir las que tu necesites.
Cuando tu ejecutas la instrucción podman search atareao
, por ejemplo, el buscará todas las imágenes con este nombre tanto en docker.io
, como en quay.io
. Indicar que por defecto busca un máximo de 25 imágenes en cada uno de los Registries que tengas configurado, pero, esto lo puedes modificar utilizando el parámetro --limit <numero>
.
¿Como gestionar imágenes con Podman?
Para gestionar imágenes con Podman tendrás que utilizar podman image <subcomando>
, donde <subcomando>
podrá ser alguno de los que encontrarás listado en man podman-image
, y que te comento a continuación.
build
build
crea una imagen a partir de un Dockerfile
. Este Dockerfile
no es mas que una receta de los pasos que tiene que seguir para construir esa imagen que tiene tanto la aplicación como todas las dependencias necesarias. Este es uno de los comandos mas interesantes y por ello le dedicaré un capítulo completo, para poder abordarlo con todo detalle. Aunque para que no te quedes con las ganas, te indico aquí como hacer tu primera imagen.
Para implementar tu primera imagen, tienes que crear dos archivos. El primero de los archivos se llamará sample.sh
, y tendrá el siguiente contenido,
#!/bin/sh
echo "Hola mundo"
A continuación tienes que crear un archivo llamado Dockerfile
, con el siguiente contenido,
FROM alpine:3.13.0
COPY ./sample.sh /
CMD /bin/sh /sample.sh
A continuación ejecuta la instrucción podman build . --tag saludos:v1
. Con el .
después de build
indicas que tiene que construir lo que se encuentra en el directorio, y con --tag
etiquetas la imagen que acabas de crear.
Aunque lo verás mas adelanta, puedes comprobar tu recién creada imagen con la instrucción, podman image list
, que te tiene que arrojar un resultado como el que te muestro a continuación,
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/saludos v1 91d342cb93b7 7 minutes ago 5.88 MB
Aquí aparece la etiqueta de tu primera imagen, un número identificativo, la fecha de creación, y el tamaño de la imagen.
diff
diff
detecta cambios en la imagen. Es decir, te muestra las diferencias con la capa anterior. Le puedes indicar el formato en el que quieres que te devuelva los resultados, aunque actualmente solo acepta el formato json.
Ahora puedes ejecutar la siguiente instrucción sobre la imagen que creaste en el apartado anterior podman image diff saludos:v1
. Esto te devuelve lo siguiente,
A /sample.sh
Precisamente sample.sh
es el archivo que has añadido en el directorio raíz de la imagen, y esa es justo la diferencia con la capa anterior.
exists
exists
comprueba si existe una imagen localmente. Para esta comprobación tenemos que proporcionarle a Podman, o bien el nombre de la imagen o bien el ID. Podman, nos devolverá 0 en el caso de que exista o 1 en el caso de que no exista. En el caso de que nos devuelva 125 estaremos ante un error de acceso al almacenamiento local. Por ejemplo,
$ podman image exists saludos:v1
$ echo $?
0
Si hubieras buscado la imagen saludos:v2
te habría devuelto un 1
.
history
history
te da información sobre la historia de la imagen, desde el momento que se creó hasta nuestros días. De nuevo, para la primera imagen que has creado con Podman, puedes ejecutar podman image history saludos:v1
. Esto te debería devolver algo similar a lo que te muestro a continuación,
ID CREATED CREATED BY SIZE COMMENT
5d506fa0fbeb 8 minutes ago /bin/sh -c #(nop) CMD /bin/sh /sample.sh 0 B
<missing> 8 minutes ago /bin/sh -c #(nop) COPY file:c294989e6814b0... 2.05 kB
7731472c3f2a 12 days ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0 B
<missing> 12 days ago /bin/sh -c #(nop) ADD file:edbe213ae0c825a... 5.88 MB
import
import
es la herramienta complementaria a export
. Te permite importar un archivo comprimido como una nueva imagen. Este archivo comprimido se obtiene a través de exportar un contenedor. Es decir, a partir del contenedor, creas una nueva imagen. Es posible modificar la imagen añadiendo determinadas opciones.
En el caso del ejemplo que estás utilizando no vas a poder crear una imagen del contenedor, porque tu contenedor se detiene inmediatamente, con lo que no te da tiempo material a hacer el export
para luego hacer el import
.
Si estás muy interesado en probar esto del import
y export
, puedes modificar el archivo sample.sh
de la siguiente forma,
#!/bin/sh
sleep 20
echo "Hola mundo"
Te estás dando 20
segundos para crear ese export
. A partir de aquí, crea la imagen como has visto anteriormente con podman build . --tag saludos:v2
, y una vez creada la ejecutas con podman run -d --name saludos2 saludos:v2
. Con esto y antes de que transcurran esos 20 minutos, tienes que exportar el contenedor a un archivo,
podman export saludos2 -o saludos2.tar
Y con esto habrás exportado el contenedor a un archivo tar
. El siguiente paso sería importarlo. Algo tan sencillo como ejecutar el siguiente comando,
podman import saludos2.tar localhost/saludos:v3
inspect
inspect
muestra información detallada de la configuración de una determinada imagen. Esta información la muestra en formato json
.
Así en nuestro caso, puedes ejecutar podman image inspect saludos:v2
, que te debería devolver un resultado como el que te muestro a continuación,
[
{
"Id": "dce32fb4130fcf543678a118c956a81e75bb617249593566276257593a644758",
"Digest": "sha256:5c8195e7d3c0fc65e9453d59f200fcb34ff65fa4d0179f391a2d9242d9c5b1ce",
"RepoTags": [
"localhost/saludos:v2"
],
"RepoDigests": [
"localhost/saludos@sha256:5c8195e7d3c0fc65e9453d59f200fcb34ff65fa4d0179f391a2d9242d9c5b1ce"
],
"Parent": "",
"Comment": "",
"Created": "2021-01-27T06:04:03.277249091Z",
"Config": {
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"/bin/sh",
"-c",
"/bin/sh /saludos2.sh"
],
"Labels": {
"io.buildah.version": "1.18.0"
}
},
"Version": "",
"Author": "",
"Architecture": "amd64",
"Os": "linux",
"Size": 5886554,
"VirtualSize": 5886554,
"GraphDriver": {
"Name": "overlay",
"Data": {
"LowerDir": "/home/lorenzo/.local/share/containers/storage/overlay/097c3bf65a7dca2825519097c11d706344469a8815d3fbeed0a95e6c29495f8f/diff:/home/lorenzo/.local/share/containers/storage/overlay/c04d1437198bc178b49fdb9a90a9c0e362ffbd63c4be5d19fec406d1c9d6a03c/diff",
"UpperDir": "/home/lorenzo/.local/share/containers/storage/overlay/193a2abeaf31bf56fdac1bc93dc9304c9174696e525d1301f20da070e9d490de/diff",
"WorkDir": "/home/lorenzo/.local/share/containers/storage/overlay/193a2abeaf31bf56fdac1bc93dc9304c9174696e525d1301f20da070e9d490de/work"
}
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:c04d1437198bc178b49fdb9a90a9c0e362ffbd63c4be5d19fec406d1c9d6a03c",
"sha256:3050e090b1e0ba49f21fb6b4abf1d49ed52dc87c9527dba28674c63c0e1f86e3",
"sha256:5f553e79b0113e70a0b180bc373d52a4cb90e330a83efee9f6d5a7b965fa10c1"
]
},
"Labels": {
"io.buildah.version": "1.18.0"
},
"Annotations": {},
"ManifestType": "application/vnd.oci.image.manifest.v1+json",
"User": "",
"History": [
{
"created": "2021-01-15T02:23:51.062843845Z",
"created_by": "/bin/sh -c #(nop) ADD file:edbe213ae0c825a5bfbe569928cf20f683f334f93a093ccd0a3a014b7428e760 in / "
},
{
"created": "2021-01-15T02:23:51.238454884Z",
"created_by": "/bin/sh -c #(nop) CMD [\"/bin/sh\"]",
"empty_layer": true
},
{
"created": "2021-01-27T06:02:11.000445095Z",
"created_by": "/bin/sh -c #(nop) COPY file:c294989e6814b092a5fa845cd1057ca9477dcab4c3a49b2f510ddb1fd6742c2f in / "
},
{
"created": "2021-01-27T06:02:11.169382092Z",
"created_by": "/bin/sh -c #(nop) CMD /bin/sh /sample.sh",
"empty_layer": true
},
{
"created": "2021-01-27T06:04:03.000412313Z",
"created_by": "/bin/sh -c #(nop) COPY file:99d0d6c19f3ac47b7becaf5f58e89af58f432a399ba1f5e427b50a4650f93ef8 in / "
},
{
"created": "2021-01-27T06:04:03.277595448Z",
"created_by": "/bin/sh -c #(nop) CMD /bin/sh /saludos2.sh",
"empty_layer": true
}
],
"NamesHistory": []
}
]
Si te fijas aquí tienes información detallada de todo lo relativo a la imagen. Por ejemplo, la fecha de creación, la arquitectura o el sistema operativo, el tamaño que ocupa. Pero no solo esto, también puedes ver la historia, tal y como la has visto con uno de los comandos anteriores, pero además con la fecha de creación.
list
list
o ls
o también lo puedes utilizar directamente como podman images
, muestra todas las imágenes que se encuentran en tu sistema.
En mi caso, el resultado es el siguiente, que diferirá del tuyo, dependiendo de las pruebas y ejemplos que hayas ido haciendo hasta aquí,
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/saludos v3 674848ed9e80 32 minutes ago 5.88 MB
localhost/saludos sleep 31ce9865fe9d 33 minutes ago 5.88 MB
localhost/saludos v2 dce32fb4130f 46 minutes ago 5.89 MB
localhost/saludos v1 7ce974065486 48 minutes ago 5.88 MB
<none> <none> 6c3afe27c334 51 minutes ago 5.88 MB
<none> <none> a36d7d5e7b2c 52 minutes ago 5.88 MB
<none> <none> 60503d0b1277 53 minutes ago 5.88 MB
<none> <none> 91d342cb93b7 About an hour ago 5.88 MB
<none> <none> 79b016843d30 About an hour ago 5.88 MB
docker.io/library/alpine 3.13.0 7731472c3f2a 12 days ago 5.88 MB
docker.io/library/alpine latest 7731472c3f2a 12 days ago 5.88 MB
load y save
load
carga una imagen desde un archivo tar
. Este archivo se crea a partir de una imagen en Podman con podman save
. Se trata de un archivo oci
o docker
. Este comando carga por defecto desde la entrada por defecto stdin
o desde un archivo utilizando la opción --input
.
Para probar este comando puedes guardar una de tus imágenes, utilizando podman save
y posteriormente restaurarla con podman load
. Por ejemplo,
$ podman save saludos:sleep -o saludos.tar
$ podman image rm saludos:seep
$ podman load -i saludos.tar
También lo puedes hacer utilizando estas otras variantes para cargar el archivo .tar
,
$ podman load < saludos.tar
$ cat saludos.tar | podman load
En este caso save
te permite guardar una imagen a un archivo tar
.
Para probar este comando puedes guardar una de tus imágenes, utilizando podman save
y posteriormente restaurarla con podman load
. Por ejemplo,
$ podman save saludos:sleep -o saludos.tar
mount y unmount
mount
monta el sistema de archivos de una imagen. Para poder hacerlo, antes de ejecutar esta instrucción tienes que ejecutar podman unshare
. Por ejemplo podman mount hello-world
. Una vez la ha conseguido montar, te devuelve el directorio en donde lo hizo. Si ejecutas esta instrucción sin argumentos, Podman te devolverá el listado de todas las imágenes que se encuentran montadas. Por ejemplo,
$ podman unshare
$ podman image mount saludos:sleep
/home/lorenzo/.local/share/containers/storage/overlay/9c27e219663c25e0f28493790cc0b88bc973ba3b1686355f221c38a36978ac63/merged
$ podman image mount --format=json
[
{
"id": "bf756fb1ae65adf866bd8c456593cd24beb6a0a061dedf42b26a993176745f6b",
"Names": [
"sha256:31b9c7d48790f0d8c50ab433d9c3b7e17666d6993084c002c2ff1ca09b96391d"
],
"Repositories": [
"docker.io/library/hello-world:latest"
],
"mountpoint": "/home/lorenzo/.local/share/containers/storage/overlay/9c27e219663c25e0f28493790cc0b88bc973ba3b1686355f221c38a36978ac63/merged"
}
]
Ahora, te queda listar el contenido del directorio que te ha devuelto al realizar el montaje, es decir,
ls -la /home/lorenzo/.local/share/containers/storage/overlay/9c27e219663c25e0f28493790cc0b88bc973ba3b1686355f221c38a36978ac63/merged
Te vas a encontrar con una estructura de directorios que te resultará tremendamente familiar,
dr-xr-xr-x 19 root root 4096 ene 28 06:39 .
drwxr-xr-x 2 root root 4096 ene 14 12:49 bin
drwxr-xr-x 2 root root 4096 ene 14 12:49 dev
drwxr-xr-x 15 root root 4096 ene 14 12:49 etc
drwxr-xr-x 2 root root 4096 ene 14 12:49 home
drwxr-xr-x 7 root root 4096 ene 14 12:49 lib
drwxr-xr-x 5 root root 4096 ene 14 12:49 media
drwxr-xr-x 2 root root 4096 ene 14 12:49 mnt
drwxr-xr-x 2 root root 4096 ene 14 12:49 opt
dr-xr-xr-x 2 root root 4096 ene 14 12:49 proc
drwx------ 2 root root 4096 ene 14 12:49 root
drwxr-xr-x 2 root root 4096 ene 14 12:49 run
-rw-rw-r-- 1 root root 39 ene 27 07:16 sample.sh
drwxr-xr-x 2 root root 4096 ene 14 12:49 sbin
drwxr-xr-x 2 root root 4096 ene 14 12:49 srv
drwxr-xr-x 2 root root 4096 ene 14 12:49 sys
drwxrwxrwt 2 root root 4096 ene 14 12:49 tmp
drwxr-xr-x 7 root root 4096 ene 14 12:49 usr
drwxr-xr-x 12 root root 4096 ene 14 12:49 var
Como te puedes imaginar umount
desmonta la imagen que hayas montado previamente. Puedes forzar a que se desmonte la imagen con --force
, y puedes desmontar todas las imágenes que se encuentren montadas actualmente utilizando --all
.
prune
prune
te permite borrar todas las imágenes que no se están utilizando. Si utilizas la opción -a
o --all
, se borrarán todas las imágenes que no estén asociadas con ningún contenedor asociado. Se trata de un comando que tienes que utilizar con sumo cuidado para evitarte alguna sorpresa desagradable.
podman image prune --all --force
También tienes una opción interesante, como es --filter
que te permite utilizar filtros para seleccionar que imágenes quieres borrar. Por ejemplo, si quisieras borrar todas las imágenes anteriores a una fecha determinada podrías hacerlo como en el siguiente ejemplo,
podman image prune --all --force --filter until=2021-1-1
pull y push
Con este comando Podman copia una imagen de un registro a la máquina en la que estés ejecutándolo. Si no has especificado otro registro, por defecto, Podman intentará traerse la imagen de Docker Hub. En el caso de que no hayas especificado ninguna etiqueta, Podman utilizará por defecto la etiqueta latest
, e intentará copiar esa imagen del registro remoto al registro local, a tu máquina. Una vez que Podman ha copiado la imagen del registro remoto en el registro local se mostrará el número identificativo de la imagen. Por ejemplo,
$ podman pull atareao/hola-mundo
Completed short name "atareao/hola-mundo" with unqualified-search registries (origin: /etc/containers/registries.conf)
Trying to pull docker.io/atareao/hola-mundo:latest...
Getting image source signatures
Copying blob 5d20c808ce19 done
Copying config 8f808bd8b0 done
Writing manifest to image destination
Storing signatures
8f808bd8b04a5f27105d184a9283f21c7850ea75db6277588fffbce689097998
Como te indicaba anteriormente, por defecto, trae la imagen de Docker Hub, pero es posible traerla de otras fuentes, al igual que será posible subirla a otras fuentes, como verás en el siguiente apartado. Por ejemplo,
podman pull quay.io/dockerlibrary/hola-mundo
Por ejemplo, si hiciste push
contra un directorio en tu equipo, puedes hacer un pull
tal y como te muestro a continuación,
podman pull dir:/tmp/temporal
Este comando hace la justo la operación opuesta al anterior, es decir, en lugar de bajar la imagen de un registro, lo que hace es subirla. Da lo mismo donde la quieras subir, ya sea un registro local como un registro remoto. También, puedes hacerlo contra un directorio, como te muestro a continuación,
podman push saludos:sleep dir:/tmp/temporal
rm
Para borrar una imagen o varias imágenes, y liberar espacio en tu equipo puedes hacerlo utilizando podman image rm <ID>
o también con podman rmi <ID>
. Si lo que quieres es borrar todas las imágenes puedes hacerlo con la opción --all
ó -a
.
Con la opción --force
o -f
, se eliminarán todos los contenedores que están correspondientes a la imagen, antes de borrar la imagen del sistema. Así, si quieres borrar todas las imágenes y contenedores lo puedes hacer con podman rmi --all --force
o podman rmi -a -f
.
search
search
te permite buscar imágenes en uno o varios registros. Puedes especificar en que registro quieres buscar alñadiendo el registro en el término de búsqueda. Por defecto, buscará en los registros que se encuentrend definidos en /etc/containers/registries.conf
. En mi caso, por ejemplo, el contenido de este archivo es,
[registries.search]
registries = ['docker.io', 'quay.io']
De esta manera buscará en los dos registros. Si solo quisieras buscarlo en uno de ellos, por ejemplo en quay.io
, lo podrías hacer de la siguiente forma,
podman search quay.io/hola-mundo
Además de esto también puedes utilizar filtros para realilzar tus búsquedas. Por ejemplo puedes buscar imágenes con un número determinado de estrellas,
podman search hola-mundo --filter stars=2
O también, buscar solo imágenes oficiales con,
podman search hola-mundo --filter is-official=true
sign
podman image sign
crea una firma local para una o mas imágenes descargadas de un registro. Con la opción --cert-dir
indicas la ruta en la que se encuentra el certificado. Con la opción --directory
especificas donde se guardará las firmas, mientras que con --sign-in
sobreescribes la identidad de la firma. Por ejemplo,
podman image sign --sign-by atareao@atareao.es --directory /tmp/signatures /tmp/temporal
tag y untag
Con estos dos comandos añades o quitas etiquetas a una imagen local. No solo es capaz de añadir una etiqueta si no también renombrar la imagen. Por ejemplo,
$ podman image tag hola:sleep hola:despierta
$ podman image tag hola:sleep adios:sleep
$ podman tag docker.io/atareao/hola-mundo saludos:sleep
En el caso de untag
tienes que tener en cuenta que quita el nombre, de la imagen almacenada localmente.
tree
Imprime la jerarquía de capas de una imagen en formato de árbol, tal y como puedes ver en el ejemplo que te muestro a continuación,
$ podman image tree localhost/saludos:sleep
Image ID: f76e3ddccbc2
Tags: [localhost/tmp/temporal:latest localhost/saludos:sleep localhost/sleepi:latest lo
calhost/saludos:sleepi]
Size: 5.884MB
Image Layers
├── ID: c04d1437198b Size: 5.88MB Top Layer of: [docker.io/library/alpine:3.13.0]
└── ID: db85b5fb6931 Size: 2.048kB Top Layer of: [localhost/tmp/temporal:latest localhost/
saludos:sleep localhost/sleepi:latest localhost/saludos:sleepi]
trust
Con este comando gestionas tu política de confianza, es decir, gestionas en que registros confias y en cuales no. Esto lo haces en base a su ubicación. Con la opción set
estables cual es la política por defecto, mientras que con show
muestras las políticasa de confianza que hay disponibles en tu sistema. Por ejemplo,
$ podman image trust show
default accept
insecureAcceptAnything
Imagen de portada de Andre Mouton en Unsplash