Compartir comentarios
Las respuestas se generan en base a la documentación.

Crear y construir una Docker Hardened Image

Las Docker Hardened Images (DHI) se construyen a partir de archivos de definición YAML declarativos en lugar de los Dockerfiles tradicionales. Un único archivo YAML describe exactamente lo que contiene una imagen: paquetes, usuarios, variables de entorno, punto de entrada (entrypoint) y metadatos. El sistema de construcción de DHI produce una imagen firmada que contiene únicamente los paquetes necesarios, con una lista de materiales de software (SBOM) y procedencia de nivel 3 de construcción de SLSA.

Esta página explica cómo escribir un archivo de definición de DHI, construir imágenes localmente y utilizar patrones avanzados como etapas de construcción (build stages), repositorios de terceros, rutas de archivos y variantes de desarrollo.

Important

El sistema de construcción de DHI descarga las imágenes base y las herramientas de construcción desde dhi.io, por lo que debes autenticarte en ese registro antes de construir un archivo de definición. Utiliza tus credenciales de Docker ID (el mismo usuario y contraseña que utilizas para Docker Hub) al iniciar sesión.

Ejecuta docker login dhi.io para autenticarte.

En qué se diferencian las construcciones de DHI de los Dockerfiles

Un Dockerfile es una secuencia de instrucciones imperativas: RUN, COPY, FROM. Un archivo de definición de DHI es una especificación declarativa. Describes el estado deseado de la imagen y el sistema de construcción determina cómo producirlo.

Cada definición de DHI comienza con una directiva de sintaxis que indica a BuildKit qué frontend de construcción de DHI utilizar. El frontend es el componente que analiza y procesa las definiciones YAML en lugar del analizador de Dockerfile predeterminado:

# syntax=dhi.io/build:2-alpine3.23

La versión del frontend corresponde a la distribución base:

DistribuciónDirectiva de sintaxis
Alpine 3.22# syntax=dhi.io/build:2-alpine3.22
Alpine 3.23# syntax=dhi.io/build:2-alpine3.23
Debian 12 (Bookworm)# syntax=dhi.io/build:2-debian12
Debian 13 (Trixie)# syntax=dhi.io/build:2-debian13

El sistema de construcción de DHI lee el archivo YAML, resuelve los paquetes de los repositorios especificados, ensambla el sistema de archivos, crea cuentas de usuario, establece los metadatos y produce una imagen OCI firmada.

Explorar el catálogo como referencia

El repositorio del catálogo DHI es de código abierto bajo la licencia Apache 2.0 y contiene cada definición de imagen oficial. Estudiar las definiciones existentes es la mejor manera de aprender los patrones YAML para los diferentes tipos de imágenes.

El catálogo sigue esta estructura de directorios:

catalog/
├── image/
│   ├── alpine-base/
│   │   ├── alpine-3.23/
│   │   │   ├── 3.23.yaml            # runtime variant
│   │   │   └── 3.23-dev.yaml        # dev variant
│   │   ├── guides.md
│   │   ├── info.yaml
│   │   ├── logo.svg
│   │   └── overview.md
│   ├── nginx/
│   │   ├── alpine-3.22/
│   │   ├── alpine-3.23/
│   │   │   ├── mainline.yaml
│   │   │   ├── mainline-dev.yaml
│   │   │   ├── stable.yaml
│   │   │   └── stable-dev.yaml
│   │   ├── debian-12/
│   │   ├── debian-13/
│   │   ├── bin/
│   │   ├── guides.md
│   │   ├── info.yaml
│   │   ├── logo.svg
│   │   └── overview.md
│   └── redis/
│       ├── debian-13/
│       │   ├── 8.0.yaml              # runtime
│       │   ├── 8.0-dev.yaml          # dev
│       │   ├── 8.0-compat.yaml       # compat runtime
│       │   └── 8.0-compat-dev.yaml   # compat dev
│       ├── guides.md
│       ├── info.yaml
│       ├── logo.svg
│       └── overview.md
├── chart/
└── package/

Cada imagen organiza sus variantes por distribución. Las imágenes admiten múltiples tipos de variantes:

  • Una variante de tiempo de ejecución (runtime) es mínima y normalmente se ejecuta como un usuario sin privilegios (non-root).
  • Una variante de desarrollo (dev) agrega un shell, un gestor de paquetes y herramientas de desarrollo.
  • Una variante de compatibilidad agrega utilidades de shell comunes como bash, coreutils, grep y sed para su uso con flujos de trabajo existentes. Las imágenes de compatibilidad utilizan el campo flavor: compat junto con una variante runtime o dev.
  • Una variante de compatibilidad y desarrollo (compatibility-dev) combina los paquetes de compatibilidad con herramientas de desarrollo.

Algunas imágenes también admiten variantes adicionales (como las variantes de framework de software sfw). Consulta el catálogo para ver la lista completa de variantes disponibles para cada imagen.

Antes de escribir tu propia definición, prueba a construir una imagen de catálogo existente directamente desde GitHub:

$ docker buildx build \
    https://raw.githubusercontent.com/docker-hardened-images/catalog/refs/heads/main/image/alpine-base/alpine-3.23/3.23.yaml \
    --sbom=generator=dhi.io/scout-sbom-indexer:1 \
    --provenance=1 \
    --tag my-alpine-base:3.23 \
    --load

Esto descarga el archivo de definición directamente desde GitHub y lo construye localmente. Una vez finalizada la construcción, verifica la imagen:

$ docker images my-alpine-base

Para modificar una imagen, clona el catálogo y edita los archivos YAML localmente:

$ git clone https://github.com/docker-hardened-images/catalog.git
$ cd catalog

Referencia del esquema YAML

Las siguientes secciones describen los campos disponibles en un archivo de definición de DHI.

Campos requeridos

Cada definición debe incluir estos campos de nivel superior:

CampoDescripción
nameNombre legible por humanos para la imagen.
imageRuta completa del registro, como dhi.io/my-image.
variantTipo de variante de la imagen: runtime o dev.
tagsLista de etiquetas de la imagen.
platformsArquitecturas de destino, como linux/amd64 y linux/arm64.
contentsRepositorios de paquetes y paquetes a instalar.

Metadatos de la imagen

Estos campos agregan metadatos a la imagen:

CampoDescripción
os-releaseDefine el contenido del archivo /etc/os-release dentro de la imagen.
annotationsAnotaciones de la imagen OCI como descripción y licencia.
datesFecha de lanzamiento y fecha de fin de soporte (end-of-life).
varsVariables en tiempo de construcción para plantillas.
flavorModificador del tipo de imagen (flavor), como compat para imágenes de compatibilidad.

Configuración del contenedor

Estos campos controlan cómo se ejecuta el contenedor:

CampoDescripción
accountsUsuarios, grupos y el usuario por defecto de ejecución (run-as).
environmentVariables de entorno.
entrypointComando del punto de entrada (entrypoint) del contenedor.
cmdArgumentos de comandos predeterminados.
work-dirDirectorio de trabajo dentro del contenedor.
volumesPuntos de montaje de volúmenes.
portsPuertos de red expuestos.
pathsDirectorios, archivos y enlaces simbólicos a crear.

Campos avanzados

Estos campos admiten patrones de construcción más complejos:

CampoDescripción
contents.buildsEtapas de construcción (build stages) con pipelines de shell.
contents.keyringClaves de firma para repositorios de paquetes de terceros.
contents.artifactsArtefactos OCI preconstruidos a incluir.
contents.mappingsAsignaciones de Package URL (purl) para la precisión de la SBOM.
contents.filesArchivos de origen obtenidos de URLs de Git con sumas de comprobación (checksums).

Crear una imagen mínima

Comienza con la definición más sencilla posible: una imagen base de Alpine con un usuario sin privilegios (non-root).

Crea un directorio para tu proyecto y agrega un archivo llamado base.yaml:

# syntax=dhi.io/build:2-alpine3.23

name: My Base Image
image: my-registry/my-base
variant: runtime
tags:
  - "1.0.0"
  - "1.0"
platforms:
  - linux/amd64
  - linux/arm64

contents:
  repositories:
    - https://dl-cdn.alpinelinux.org/alpine/v3.23/main
    - https://dl-cdn.alpinelinux.org/alpine/v3.23/community
  packages:
    - alpine-baselayout-data
    - busybox
    - ca-certificates-bundle

accounts:
  run-as: nonroot
  users:
    - name: nonroot
      uid: 65532
      gid: 65532
  groups:
    - name: nonroot
      gid: 65532
      members:
        - nonroot

os-release:
  name: Docker Hardened Images (Alpine)
  id: alpine
  version-id: "3.23"
  pretty-name: My Hardened Image
  home-url: https://docker.com/products/hardened-images/
  bug-report-url: https://docker.com/support/

environment:
  SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt

annotations:
  org.opencontainers.image.description: A minimal Alpine base image

cmd:
  - /bin/sh

En esta definición:

  • contents.repositories utiliza URLs completas a espejos (mirrors) de paquetes de Alpine.
  • contents.packages enumera los nombres exactos de los paquetes de Alpine.
  • El bloque accounts crea un usuario nonroot (UID 65532) y lo establece como el usuario predeterminado para el contenedor.
  • El bloque os-release define lo que aparece en /etc/os-release. Incluye siempre bug-report-url junto con home-url.
  • El bloque annotations añade metadatos OCI visibles en los registros y en los informes de Docker Scout.

Construye la imagen:

$ docker buildx build . -f base.yaml \
    --sbom=generator=dhi.io/scout-sbom-indexer:1 \
    --provenance=1 \
    --tag my-base:latest \
    --load
Note

El campo tags en el archivo de especificación define los metadatos de la imagen (etiquetas de variante y versión integradas en el manifiesto de la imagen). La opción --tag en la CLI establece la referencia de la imagen OCI utilizada para subir (push) o cargar (load) la imagen. Estos tienen propósitos diferentes: las etiquetas del archivo de especificación describen qué es la imagen, mientras que la etiqueta de la CLI determina dónde se almacena.

Utilizar una base Debian con repositorios de terceros

Para aplicaciones que requieren paquetes de Debian o repositorios APT de terceros, utiliza la directiva de sintaxis de Debian. El siguiente ejemplo construye una imagen de Redis a partir del repositorio APT oficial de Redis.

Crea un archivo llamado redis.yaml:

# syntax=dhi.io/build:2-debian13

name: Redis 8.0.x
image: my-registry/my-redis
variant: runtime
tags:
  - "8.0"
  - "8.0.5"
platforms:
  - linux/amd64
  - linux/arm64

contents:
  repositories:
    - deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb trixie main
  keyring:
    - https://packages.redis.io/gpg
  packages:
    - '!libelogind0'
    - '!mawk'
    - '!original-awk'
    - base-files
    - libpcre2-8-0
    - libssl3t64
    - libstdc++6
    - libsystemd0
    - redis=6:8.0.5-1rl1~trixie1
    - redis-server=6:8.0.5-1rl1~trixie1
    - redis-tools=6:8.0.5-1rl1~trixie1
    - tini
  mappings:
    redis: pkg:deb/redis/redis@6:8.0.5-1rl1~trixie1?os_name=debian&os_version=13
    redis-server: pkg:deb/redis/redis-server@6:8.0.5-1rl1~trixie1?os_name=debian&os_version=13
    redis-tools: pkg:deb/redis/redis-tools@6:8.0.5-1rl1~trixie1?os_name=debian&os_version=13

accounts:
  run-as: nonroot
  users:
    - name: nonroot
      uid: 65532
      gid: 65532
  groups:
    - name: nonroot
      gid: 65532
      members:
        - nonroot

os-release:
  name: Docker Hardened Images (Debian)
  id: debian
  version-id: "13"
  version-codename: trixie
  pretty-name: Docker Hardened Images/Debian GNU/Linux 13 (trixie)
  home-url: https://docker.com/products/hardened-images/
  bug-report-url: https://docker.com/support/

work-dir: /data

environment:
  REDIS_VERSION: 8.0.5

annotations:
  org.opencontainers.image.description: A minimal Redis image
  org.opencontainers.image.licenses: AGPL-3.0-only

entrypoint:
  - /usr/bin/tini
  - --

cmd:
  - redis-server
  - /etc/redis/redis.conf
  - --include
  - /etc/redis/conf.d/*.conf

Este ejemplo introduce varios patrones:

  • Repositorios de terceros: El campo repositories utiliza el formato deb [signed-by=...] URL suite component de Debian para las fuentes de APT.
  • Llavero de claves (Keyring): El campo keyring descarga la clave GPG utilizada para verificar los paquetes del repositorio de terceros.
  • Exclusiones de paquetes: Antepón un signo ! al nombre de un paquete para excluirlo explícitamente. Esto evita que se instalen dependencias no deseadas. En este caso, se excluyen !libelogind0, !mawk y !original-awk.
  • Fijación de versión de Debian: Utiliza el formato completo con epoch, redis-server=6:8.0.5-1rl1~trixie1, para fijar las versiones exactas de los paquetes.
  • Asignaciones de SBOM: El campo mappings proporciona metadatos de Package URL (purl) para que Docker Scout pueda identificar con precisión el software en la SBOM.
  • Proceso de inicio: El punto de entrada (entrypoint) utiliza tini como un proceso de inicio ligero (PID 1) para gestionar el reenvío de señales y la eliminación de procesos zombi.
  • Inclusión de configuración: El comando (cmd) utiliza --include /etc/redis/conf.d/*.conf para que los archivos de configuración creados en la sección paths se carguen al inicio.

Crear rutas

Utiliza el campo paths para crear directorios, archivos con contenido en línea y enlaces simbólicos dentro de la imagen. El siguiente ejemplo amplía la definición de Redis con las rutas requeridas para su funcionamiento:

paths:
  - type: directory
    path: /var/lib/redis
    uid: 65532
    gid: 65532
    mode: "0755"
  - type: directory
    path: /var/log/redis
    uid: 65532
    gid: 65532
    mode: "0755"
  - type: directory
    path: /run/redis/
    uid: 65532
    gid: 65532
    mode: "0755"
  - type: directory
    path: /data
    uid: 65532
    gid: 65532
    mode: "0755"
  - type: file
    path: /etc/redis/conf.d/docker.conf
    content: |
      daemonize no
      bind 0.0.0.0 -::1
      logfile ""
    uid: 0
    gid: 0
    mode: "0555"
  - type: symlink
    path: /usr/bin/redis-sentinel
    uid: 0
    gid: 0
    source: /usr/bin/redis-check-rdb

Hay tres tipos de rutas disponibles:

TipoCampos requeridosDescripción
directorypath, uid, gid, modeCrea un directorio vacío.
filepath, content, uid, gid, modeCrea un archivo con contenido en línea.
symlinkpath, source, uid, gidCrea un enlace simbólico.

El campo mode utiliza una representación en cadena de los bits de permisos octales, como "0755" para lectura-escritura-ejecución por parte del propietario o "0555" para lectura-ejecución por parte de todos. Ten en cuenta que el tipo file admite content en línea utilizando una cadena multilínea de YAML.

Agregar etapas de construcción

Para las imágenes que necesitan ejecutar comandos de shell durante la construcción, como la configuración de archivos, la creación de enlaces simbólicos o el ajuste de permisos, utiliza el campo contents.builds. Cada etapa de construcción (build stage) tiene sus propios paquetes, un pipeline de pasos nombrados y asignaciones de salida.

El siguiente ejemplo configura Nginx durante la construcción para que se ejecute en un puerto sin privilegios y deshabilite los tokens de servidor:

# syntax=dhi.io/build:2-alpine3.23

name: Nginx mainline
image: my-registry/my-nginx
variant: runtime
tags:
  - "1.29"
platforms:
  - linux/amd64
  - linux/arm64

contents:
  repositories:
    - https://dl-cdn.alpinelinux.org/alpine/v3.23/main
    - https://dl-cdn.alpinelinux.org/alpine/v3.23/community
    - http://nginx.org/packages/mainline/alpine/v3.23/main
  keyring:
    - https://nginx.org/keys/nginx_signing.rsa.pub
  packages:
    - alpine-baselayout-data
    - busybox
    - musl-utils
    - nginx=1.29.5-r1
  builds:
    - name: nginx
      contents:
        repositories:
          - https://dl-cdn.alpinelinux.org/alpine/v3.23/main
          - https://dl-cdn.alpinelinux.org/alpine/v3.23/community
          - http://nginx.org/packages/mainline/alpine/v3.23/main
        keyring:
          - https://nginx.org/keys/nginx_signing.rsa.pub
        packages:
          - alpine-baselayout-data
          - bash
          - musl-utils
          - nginx=1.29.5-r1
      pipeline:
        - name: install
          runs: |
            set -eux -o pipefail

            ln -sf /dev/stdout /var/log/nginx/access.log
            ln -sf /dev/stderr /var/log/nginx/error.log

            sed -i "s,listen       80;,listen       8080;," /etc/nginx/conf.d/default.conf
            sed -i "/user  nginx;/d" /etc/nginx/nginx.conf
            sed -i "s,pid        /run/nginx.pid;,pid        /var/run/nginx.pid;," /etc/nginx/nginx.conf
            sed -i '/^http {$/a\    server_tokens off;' /etc/nginx/nginx.conf

            chown -R 65532:65532 /var/cache/nginx
            chmod -R g+w /var/cache/nginx
            chown -R 65532:65532 /etc/nginx
            chmod -R g+w /etc/nginx
            chown -R 65532:65532 /run
            chown -R 65532:65532 /run/lock
            chown -R 65532:65532 /var/run
            chown -R 65532:65532 /var/log/nginx
      outputs:
        - source: /
          target: /
          uid: 0
          gid: 0
          diff: true

accounts:
  run-as: nginx
  users:
    - name: nginx
      uid: 65532
      gid: 65532
  groups:
    - name: nginx
      gid: 65532
      members:
        - nginx
    - name: www-data
      gid: 82

os-release:
  name: Docker Hardened Images (Alpine)
  id: alpine
  version-id: "3.23"
  pretty-name: Docker Hardened Images/Alpine Linux v3.23
  home-url: https://docker.com/products/hardened-images/
  bug-report-url: https://docker.com/support/

environment:
  NGINX_VERSION: 1.29.5-r1

annotations:
  org.opencontainers.image.description: A minimal Nginx image
  org.opencontainers.image.licenses: BSD-2-Clause

entrypoint:
  - nginx

cmd:
  - -g
  - daemon off;

ports:
  - 8080/tcp

Patrones clave en esta definición:

ElementoDescripción
contentsCada etapa de construcción tiene su propia sección contents. Incluye paquetes necesarios únicamente durante la construcción, como bash.
pipelineContiene pasos nombrados que ejecutan comandos de shell. Comienza siempre los scripts con set -eux -o pipefail.
outputsCopia los resultados de la etapa de construcción a la imagen final. Al establecer diff: true, se copian únicamente los archivos que cambiaron, manteniendo la imagen mínima.
accountsNginx utiliza un usuario nginx dedicado (UID 65532) en lugar de nonroot. El grupo www-data (GID 82) también se crea para la compatibilidad con el servidor web.
musl-utilsRequerido tanto en los paquetes principales como en los de construcción para las imágenes de Nginx basadas en Alpine.

Utilizar artefactos OCI como fuentes de paquetes

En lugar de instalar paquetes desde los repositorios de Alpine o Debian, puedes descargar binarios preconstruidos a partir de los artefactos de paquetes de DHI. Así es como el catálogo construye imágenes como Python y Node.js: el entorno de ejecución se compila por separado y se publica como un artefacto OCI, y luego se referencia por su digest en la definición de la imagen.

Agrega el campo artifacts bajo contents:

contents:
  repositories:
    - https://dl-cdn.alpinelinux.org/alpine/v3.23/main
    - https://dl-cdn.alpinelinux.org/alpine/v3.23/community
  packages:
    - alpine-baselayout-data
    - bzip2
    - ca-certificates-bundle
    - expat
    - gdbm
    - libffi
    - mpdecimal
    - musl
    - ncurses
    - openssl
    - readline
    - sqlite-libs
    - tzdata
    - zlib
  artifacts:
    - name: dhi.io/pkg-python:3.13.12-alpine3.23@sha256:052b3b915055006a27c42470eed5c65d7ee92d2c3de47ecaedcc6bbd36077b95
      includes:
        - opt/**
      uid: 0
      gid: 0
CampoDescripción
nameReferencia OCI completa con fijación de digest. Utiliza siempre @sha256: para garantizar la reproducibilidad.
includesPatrones de coincidencia (glob) para los archivos a extraer del artefacto. Las rutas se resuelven desde la raíz del sistema de archivos; opt/** incluye todo lo que se encuentra bajo la ruta /opt.
excludesPatrones de coincidencia (glob) para los archivos a omitir. Útil para eliminar cabeceras, documentación o binarios no utilizados.
uid, gidPropietario y grupo para los archivos extraídos.

Los paquetes DHI disponibles se encuentran en el directorio package/ del repositorio del catálogo.

Crear una variante de desarrollo

Una variante de desarrollo (dev) de una imagen añade un shell, un gestor de paquetes y herramientas de desarrollo. Esto es útil para la depuración y para su uso como una etapa de construcción en flujos de trabajo de varias etapas.

Para crear una variante de desarrollo, cambia el campo variant y habilita el acceso root:

# syntax=dhi.io/build:2-alpine3.23

name: Alpine 3.23 Base (dev)
image: my-registry/my-base
variant: dev
tags:
  - "1.0-dev"
platforms:
  - linux/amd64
  - linux/arm64

contents:
  repositories:
    - https://dl-cdn.alpinelinux.org/alpine/v3.23/main
    - https://dl-cdn.alpinelinux.org/alpine/v3.23/community
  packages:
    - alpine-baselayout-data
    - apk-tools
    - busybox
    - ca-certificates-bundle

accounts:
  root: true
  run-as: root
  users:
    - name: nonroot
      uid: 65532
      gid: 65532
  groups:
    - name: nonroot
      gid: 65532
      members:
        - nonroot

os-release:
  name: Docker Hardened Images (Alpine)
  id: alpine
  version-id: "3.23"
  pretty-name: Docker Hardened Images/Alpine Linux v3.23
  home-url: https://docker.com/products/hardened-images/
  bug-report-url: https://docker.com/support/

environment:
  SSL_CERT_FILE: /etc/ssl/certs/ca-certificates.crt

annotations:
  org.opencontainers.image.description: A minimal Alpine base image

cmd:
  - /bin/sh

Las diferencias clave con respecto a una variante de ejecución (runtime):

  • variant: dev en lugar de variant: runtime.
  • accounts.root: true habilita la cuenta root.
  • run-as: root establece root como el usuario predeterminado.
  • Se añade apk-tools a los paquetes, dotando a la imagen de un gestor de paquetes.
  • El usuario nonroot se sigue definiendo para que las aplicaciones puedan cambiar a un usuario sin privilegios en tiempo de ejecución.

Para las variantes de desarrollo basadas en Debian, añade apt en lugar de apk-tools e incluye la variable de entorno DEBIAN_FRONTEND: noninteractive.

Crear una variante de compatibilidad

Una variante de compatibilidad incluye utilidades comunes de shell para su uso con scripts y herramientas de automatización que esperan un entorno de usuario estándar de Linux. Las imágenes de compatibilidad utilizan el campo flavor:

variant: runtime
flavor: compat

Una variante de compatibilidad añade paquetes como bash, coreutils, findutils, grep, hostname, openssl, procps y sed junto a los paquetes de la aplicación. Una variante de compatibilidad y desarrollo (compatibility-dev) combina tanto los paquetes de compatibilidad como las herramientas de desarrollo:

variant: dev
flavor: compat

Consulta las imágenes de compatibilidad de Redis en el catálogo para ver un ejemplo completo del patrón de compatibilidad.

Configurar puertos y volúmenes

Utiliza el campo ports para declarar qué puertos expone el contenedor. Utiliza siempre puertos sin privilegios (superiores al 1024) cuando el contenedor se ejecute como un usuario no root.

ports:
  - 8080/tcp

Utiliza el campo volumes para declarar los puntos de montaje de volúmenes:

volumes:
  - /data

Configurar anotaciones

Las anotaciones OCI añaden metadatos legibles por máquina a la imagen. Utiliza el campo annotations:

annotations:
  org.opencontainers.image.description: A minimal hardened application image
  org.opencontainers.image.licenses: Apache-2.0

Estas anotaciones aparecen en los informes de Docker Scout y en las interfaces del registro de contenedores.

Construir y verificar

Construir la imagen

Construye una imagen de una sola plataforma para pruebas locales:

$ docker buildx build . -f my-image.yaml \
    --sbom=generator=dhi.io/scout-sbom-indexer:1 \
    --provenance=1 \
    --tag my-image:latest \
    --load

Inspeccionar la SBOM

Visualiza la lista de materiales de software (SBOM) generada:

$ docker scout sbom my-image:latest

Escanear en busca de vulnerabilidades

Comprueba la imagen contra las bases de datos de CVE conocidas:

$ docker scout cves my-image:latest

Comparar con una imagen no endurecida

Mide la mejora de la seguridad frente a una imagen equivalente no endurecida:

$ docker scout compare my-image:latest \
    --to <non-hardened-equivalent>:<tag> \
    --platform linux/amd64

Reemplaza <non-hardened-equivalent> con la Docker Official Image o la imagen de la comunidad con la que te estás comparando.

Inspeccionar con Docker Debug

Verifica la configuración de os-release y entrypoint:

$ docker debug my-image:latest

La salida muestra el nombre de la distribución detectada a partir de tu configuración de os-release y ejecuta una comprobación de linter del punto de entrada.

Subir a un registro

Etiqueta y sube la imagen a tu registro de contenedores:

$ docker tag my-image:latest <your-namespace>/my-image:latest
$ docker push <your-namespace>/my-image:latest

Reemplaza <your-namespace> con tu nombre de usuario de Docker Hub o el espacio de nombres de tu organización.

Docker Hardened Images es un proyecto de código abierto. Puedes contribuir con nuevas definiciones de imágenes o mejorar las existentes enviando una solicitud de extracción (pull request) al repositorio del catálogo.

Para contribuir con una nueva imagen:

  1. Haz un fork del repositorio del catálogo.
  2. Crea un directorio bajo image/ siguiendo la convención de nomenclatura: image/<image-name>/<distribution>/.
  3. Añade tus archivos de definición YAML (uno por variante).
  4. Añade un info.yaml con el nombre para mostrar, la descripción y las categorías.
  5. Añade un overview.md que describa la imagen.
  6. Añade un logo.svg para el icono de la imagen.
  7. Añade un guides.md con la documentación de uso.
  8. Abre una solicitud de extracción (pull request) contra la rama main.

Para obtener más detalles, lee la guía de contribución en el repositorio del catálogo.