Cómo y cuándo usar etiquetas de Docker / anotaciones de contenedores OCI
3 de noviembre de 2021
0 minutos de lecturaLa mayoría de las imágenes de contenedor se crean con Dockerfiles que combinan instrucciones como FROM, RUN, COPY, ENTRYPOINT, entre otras, para crear las capas de una imagen compatible con OCI. Sin embargo, hay una instrucción que se usa sorprendentemente poco: LABEL. En esta publicación, analizaremos las etiquetas («anotaciones» en la especificación de imágenes OCI): qué son, algunos usos estandarizados y prácticas que puedes aplicar para mejorar la seguridad de tus contenedores.
En el resto de este artículo, las llamaremos etiquetas —en lugar de anotaciones—, ya que es el término más usado. ¡Comencemos!
¿Qué son las etiquetas de imagen de Docker?
Las etiquetas de imagen de Docker te permiten agregar metadatos de clave-valor a la imagen. Estos datos no se exponen a los contenedores que se ejecutan a partir de ella, pero son útiles para registrar, por ejemplo, dónde está el código fuente de la imagen, quién brinda soporte o qué compilación de CI la creó.
Explicación de los metadatos de imágenes de Docker / OCI
Si alguna vez creaste un paquete de software, sabes que, por lo general, incluye el software, la configuración y, a veces, datos funcionales, además de metadatos sobre el propio paquete.
Por ejemplo, aunque los archivos Java .jar son básicamente archivos .zip, todos tienen un directorio META-INF de nivel superior que contiene varios archivos y directorios que, según la especificación de la plataforma Java 2, «... la plataforma Java 2 reconoce e interpreta para configurar aplicaciones, extensiones, cargadores de clases y servicios». Si abrimos un archivo .jar creado con la popular herramienta de compilación Maven, normalmente encontraremos, entre otras cosas, un directorio maven con contenido como el pom.xml efectivo de Maven y el pom.properties que se usaron para crear el archivo .jar. (Por si te lo preguntas, “POM” significa Project Object Model [modelo de objetos del proyecto] de Maven).
RPM, APT, NPM y la mayoría de las demás herramientas de empaquetado almacenan metadatos similares. Las herramientas los usan para instalar o ejecutar el software incluido, o bien con fines prácticos en repositorios o sistemas de monitoreo en tiempo de ejecución.

Las imágenes de contenedor también almacenan metadatos en sus capas. Si consultas el «historial» de una imagen, a menudo verás capas de cero bytes, porque no contienen cambios en el sistema de archivos, sino metadatos que se usan en tiempo de ejecución y que suelen agregarse mediante comandos de Dockerfile:
USER: usuario con el que se ejecutará el procesoENV: variable (y su valor) que se establecerá en el entorno de los procesosARG: argumento de compilación que se pasa al contenedor de compilación y se usa como una variable de entorno durante la compilaciónCMD: comando o parámetros para iniciar el proceso (ENTRYPOINT es similar)LABEL: pares de clave-valor que el motor de ejecución no usa
La mayoría de estos elementos son conocidos y se usan en todos los Dockerfiles, pero las etiquetas suelen pasarse por alto porque sus metadatos no son necesarios para ejecutar los contenedores.
Por qué deberías usar etiquetas en las imágenes de contenedor
Hay muchos motivos para usar etiquetas en tus imágenes, como documentar versiones, incluir los datos de contacto de quienes mantienen el proyecto o incluso información sobre el uso en tiempo de ejecución. Uno de los casos de uso más comunes es documentar cómo se creó la imagen, información que puede servir en la cadena de suministro de software del artefacto de imagen.
Tipos de metadatos de etiquetas de Docker / anotaciones de imágenes OCI
Etiquetas estandarizadas
Los metadatos sobre la creación y el origen de las imágenes se usan con tanta frecuencia que el equipo de OCI publica un conjunto estandarizado de claves, todas con el prefijo «org.opencontainers.image.», entre ellas:
source: URL para obtener el código fuente con el que se crea la imagenrevision: identificador de la revisión del control de versiones del software empaquetadobase.digest: resumen (hash) de la imagen en la que se basa esta imagenbase.name: referencia de la imagen en la que se basa esta imagenversion: versión del software empaquetado
Etiquetas personalizadas
Como son simplemente pares de clave-valor, tu proyecto u organización puede especificar prácticamente cualquier dato. Algunas ideas (todas podrían llevar un prefijo como «com.mycorp.myteam.»):
ci-build: URL de la ejecución del proyecto de CI que creó la imagenreleasenotes: notas de la versión del software empaquetadohealthz: endpoint HTTP para realizar comprobaciones de estadodocker.run: ejemplo de un comando de Docker para ejecutar esta imagenk8s.deployment: YAML en Base64 para una implementación de Kubernetes que use esta imagen
Este último ejemplo es interesante porque, sí, puedes almacenar como valor de una clave de etiqueta prácticamente cualquier dato que puedas codificar en Base64. Esto significa que puedes descargar esa imagen y ejecutar algo como lo siguiente para obtener un archivo YAML de ejemplo para la implementación, que luego podrías usar en un clúster de Kubernetes:
Incluso podrías canalizarlo directamente a kubectl e implementarlo de inmediato, sin necesidad de gráficos de Helm ni archivos YAML separados en tu repositorio de Git.
Cómo aprovechar las etiquetas de Docker / anotaciones OCI
Como puedes imaginar, las etiquetas pueden incluir cualquier valor al que tenga acceso tu sistema de CI y servir para vincular imágenes o contenedores en ejecución con su código fuente, documentación y más, con solo inspeccionarlas. Por ejemplo, supongamos que tu organización publica imágenes con la etiqueta estándar de OCI org.opencontainers.image.source, que incluye la URL del repositorio de control de código fuente del que proviene la imagen. Si quisieras averiguar qué imágenes de repositorios se están ejecutando en un host de Docker determinado, podrías ejecutar algo como esto:
El resultado muestra los ID de dos contenedores en ejecución. Uno tiene la etiqueta, por lo que también se muestra su valor.
La situación se complica un poco en un clúster de Kubernetes, donde probablemente no tendrás acceso a los sockets del motor de contenedores en los nodos del clúster. Lamentablemente, no hay una API para obtener estas etiquetas con kubectl, así que tendremos que buscar una alternativa. El siguiente script de Bash encuentra las imágenes que se ejecutan en el espacio de nombres del contexto actual y luego consulta el registro de imágenes para obtener sus metadatos y mostrar la información de las etiquetas:
Ten en cuenta que uso la excelente herramienta regctl del proyecto de código abierto regclient, que permite obtener información sobre imágenes directamente desde un registro, sin tener que descargar una imagen a mi entorno local para inspeccionarla. Esto también me permite ejecutar el script donde quiera, sin necesidad de tener un motor de ejecución de contenedores.
Ahora, ejecutemos este comando en un clúster y busquemos los repositorios de las imágenes que están en ejecución:
Como puedes ver, actualmente hay dos imágenes en mi clúster que se ejecutan en pods y tienen la etiqueta org.opencontainers.image.source.
Aunque estos ejemplos son relativamente sencillos, seguro que puedes ampliar estos conceptos para crear tus propios scripts o llamadas a la API según las necesidades de tu organización.
Integración con Snyk
Uno de los aspectos más interesantes desde el punto de vista de la seguridad es que el escaneo de imágenes de Snyk ahora permite vincular automáticamente la imagen escaneada con su Dockerfile mediante las etiquetas de imagen.
La integración del repositorio de código fuente de Snyk ya puede detectar y escanear estáticamente los Dockerfiles que encuentra en tu código, así como las imágenes importadas desde tus registros de contenedores. Sin embargo, hasta hace poco, tenías que gestionar por tu cuenta la correlación entre ambos. Debías agregar manualmente la referencia al Dockerfile en la imagen o implementar tu propia automatización mediante llamadas a la API.
Ahora solo tienes que incluir la etiqueta estándar de OCI org.opencontainers.image.source con la URL del repositorio que contiene el Dockerfile. Cuando se importe la imagen, Snyk se encargará de vincularlos automáticamente.

Ejemplo de un proyecto de escaneo de imágenes vinculado automáticamente
Para terminar
En resumen, las etiquetas y anotaciones de imagen, que a menudo se olvidan, son una herramienta eficaz para insertar metadatos directamente en tus imágenes. Usar claves estandarizadas puede ayudarte no solo a documentar el origen de una imagen, sino también a aprovechar herramientas de implementación y seguridad para comprender mejor el entorno que tienes implementado.
Puedes empezar a aprovechar hoy mismo la función de vinculación automática de imágenes de Snyk: solo agrega la etiqueta estándar de OCI org.opencontainers.image.source a los Dockerfiles que ya se están escaneando en tu cuenta. ¿Todavía no tienes una cuenta de Snyk? Regístrate gratis y empieza a usarla ahora.
Me interesa saber cómo usas las etiquetas. ¿Son ideas nuevas para ti o tus proyectos ya las usan? ¿Qué otras formas interesantes tienes de anotar tus imágenes? ¿Hay alguna integración nueva que te gustaría ver, con Snyk o con otras herramientas? Etiquétame (@ericsmalling) en Twitter; ¡me encantaría conocer tu opinión!
Seguridad de contenedores centrada en los desarrolladores
Snyk encuentra y corrige automáticamente vulnerabilidades en imágenes de contenedores y cargas de trabajo de Kubernetes.
