¿QUÉ ES Y POR QUÉ ES CRUCIAL?
Los contenedores empaquetan la aplicación junto con sus dependencias del sistema operativo. La seguridad en contenedores abarca desde el análisis de la configuración del Dockerfile (linting) hasta el escaneo de paquetes del SO en busca de vulnerabilidades conocidas en las capas de la imagen, incluyendo capas heredadas de la imagen base que el equipo ni siquiera escribió.
⚠️ RIESGOS Y AMENAZAS EN ESTA ETAPA:
- Ejecución del proceso principal como usuario `root` dentro del contenedor.
- Inclusión de secretos y claves API en instrucciones `ENV` o `ARG` del Dockerfile (quedan en el historial de capas).
- Uso de imágenes base desactualizadas o de proveedores no confiables, con vulnerabilidades críticas a nivel de sistema operativo.
🧰 CATÁLOGO DE HERRAMIENTAS DESTACADAS
Trivy Container
Open Source (Apache-2.0)Escáner líder de Aqua Security para detectar vulnerabilidades en paquetes de SO (apt, apk, yum) y librerías de aplicación dentro de imágenes Docker/OCI, incluyendo cada capa por separado.
Hadolint
Open Source (GPL-3.0)Linter para Dockerfiles construido sobre el parser de ShellCheck, que verifica mejores prácticas (ej. fijar versiones, evitar `ADD` remoto) e identifica instrucciones potencialmente inseguras antes de siquiera construir la imagen.
Dockle
Open Source (Apache-2.0)Auditor de seguridad para imágenes de contenedor ya construidas, enfocado en cumplimiento de estándares CIS Docker Benchmark y buenas prácticas de construcción (metadata, usuario, permisos).
Grype
Open Source (Apache-2.0)Escáner rápido de vulnerabilidades para imágenes de contenedor, sistemas de archivos y SBOMs (integra directamente con Syft), desarrollado por el mismo equipo de Anchore.
🔧 INTEGRACIÓN EN PIPELINES DE CI/CD
Ejemplos listos para copiar y adaptar. El objetivo es que el job falle (exit code ≠ 0) y bloquee el merge/deploy cuando aparece un hallazgo de severidad alta -- ese es el "gate" real de DevSecOps.
name: container-security
on: [push, pull_request]
jobs:
docker-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Hadolint - lint del Dockerfile
uses: hadolint/hadolint-action@v3.1.0
with:
dockerfile: Dockerfile
- name: Build de la imagen
run: docker build -t mi-app:${{ github.sha }} .
- name: Trivy - scan de vulnerabilidades de la imagen
uses: aquasecurity/trivy-action@master
with:
scan-type: 'image'
image-ref: 'mi-app:${{ github.sha }}'
exit-code: '1'
severity: 'CRITICAL,HIGH'
trigger:
- main
pr:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- checkout: self
- script: |
docker run --rm -i hadolint/hadolint < Dockerfile
displayName: 'Hadolint - lint del Dockerfile'
- task: Docker@2
displayName: 'Build de la imagen'
inputs:
command: build
Dockerfile: '**/Dockerfile'
tags: '$(Build.BuildId)'
repository: 'mi-app'
- script: |
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin
trivy image --severity CRITICAL,HIGH --exit-code 1 mi-app:$(Build.BuildId)
displayName: 'Trivy - scan de vulnerabilidades de la imagen'
- Utilizar siempre un usuario no privilegiado (`USER appuser`) en el Dockerfile.
- Partir de imágenes base oficiales, livianas y con firma verificable (Alpine, Distroless, Chainguard).
- Nunca declarar variables de entorno con credenciales (`ENV AWS_KEY=...`) en el Dockerfile; usar secret mounts de BuildKit.