TL;DR

  • Что: Сканирование Docker-образов на уязвимости, ошибки конфигурации и секреты перед деплоем
  • Зачем: 87% образов контейнеров содержат как минимум одну уязвимость высокой критичности
  • Инструменты: Trivy (быстрейший, бесплатный), Snyk (лучшая ремедиация), Grype (лёгкий)
  • Ключевая метрика: Ноль критических/высоких уязвимостей в продакшен-образах
  • Начните здесь: Добавьте trivy image ваш-образ:tag в ваш CI-пайплайн сегодня

Количество нарушений безопасности контейнеров выросло на 300% в 2025 году, при этом уязвимые Docker-образы являются основным вектором атак. Одна непатченная зависимость в базовом образе может раскрыть всю вашу инфраструктуру. Тем не менее, большинство команд до сих пор деплоят контейнеры без сканирования безопасности.

Это руководство охватывает внедрение комплексного тестирования и безопасности Docker-образов. Вы научитесь сканировать уязвимости, обнаруживать ошибки конфигурации, интегрировать безопасность в CI/CD пайплайны и устанавливать практики, которые сохранят ваши контейнеры в безопасности.

Что вы узнаете:

  • Как сканировать Docker-образы на уязвимости с Trivy, Snyk и Grype
  • Автоматизированные security gates в CI/CD пайплайнах
  • Выбор базовых образов и стратегии hardening
  • Обнаружение секретов и сканирование конфигурации
  • Лучшие практики организаций, управляющих безопасными контейнерными платформами

Понимание безопасности Docker-образов

Почему Docker-образы уязвимы

Docker-образы наследуют уязвимости из нескольких источников:

  • Базовые образы: Alpine, Ubuntu, Debian содержат CVE на уровне ОС
  • Пакетные менеджеры: npm, pip, Maven зависимости с известными уязвимостями
  • Код приложения: Ваш собственный код с проблемами безопасности
  • Ошибки конфигурации: Запуск от root, открытые порты, небезопасные настройки
  • Встроенные секреты: Случайно закоммиченные учётные данные

Ландшафт сканирования безопасности

Тип сканераЧто находитПримеры
Сканер уязвимостейCVE в пакетахTrivy, Grype, Clair
Сканер конфигурацииПроблемы DockerfileHadolint, Dockle
Сканер секретовУтечки учётных данныхTrivy, GitLeaks
Генератор SBOMПолный список зависимостейSyft, Trivy

Ключевые метрики безопасности

Отслеживайте эти метрики для безопасности контейнеров:

  • Критические/Высокие CVE: Цель 0 в продакшене
  • Среднее время ремедиации: Цель <24 часов для критических
  • Покрытие сканированием: 100% образов отсканированы перед деплоем
  • Процент ложных срабатываний: <5% (настройте ваш сканер)

Внедрение сканирования уязвимостей с Trivy

Предварительные требования

Перед началом убедитесь, что у вас есть:

  • Установленный Docker
  • Установленный Trivy (brew install trivy или apt install trivy)
  • Доступ к CI/CD пайплайну
  • Учётные данные для container registry

Шаг 1: Базовое сканирование образов

Сканируйте любой Docker-образ одной командой:

# Сканирование локального образа
trivy image myapp:latest

# Сканирование удалённого образа
trivy image nginx:1.25

# Пример вывода:
# nginx:1.25 (debian 12.4)
# Total: 142 (UNKNOWN: 0, LOW: 87, MEDIUM: 45, HIGH: 8, CRITICAL: 2)

Фильтрация по критичности:

# Показать только высокие и критические уязвимости
trivy image --severity HIGH,CRITICAL myapp:latest

# Выход с кодом ошибки при высоких/критических (для CI/CD)
trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:latest

Шаг 2: Сканирование во время Docker Build

Интегрируйте сканирование в процесс сборки:

# Dockerfile со сканированием безопасности
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

# Этап сканирования безопасности
FROM aquasec/trivy:latest AS scanner
COPY --from=builder /app /app
RUN trivy filesystem --exit-code 1 --severity HIGH,CRITICAL /app

# Финальный продакшен-образ
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
USER node
EXPOSE 3000
CMD ["node", "dist/index.js"]

Шаг 3: Интеграция CI/CD

Workflow GitHub Actions:

name: Container Security

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:

      - uses: actions/checkout@v4

      - name: Build image
        run: docker build -t myapp:${{ github.sha }} .

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:${{ github.sha }}
          format: 'sarif'
          output: 'trivy-results.sarif'
          severity: 'CRITICAL,HIGH'
          exit-code: '1'

      - name: Upload Trivy scan results
        uses: github/codeql-action/upload-sarif@v2
        if: always()
        with:
          sarif_file: 'trivy-results.sarif'

      - name: Run Trivy for secrets
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:${{ github.sha }}
          scan-type: 'fs'
          scanners: 'secret'
          exit-code: '1'

Проверка

Убедитесь, что ваша настройка работает:

  • trivy image выполняется без ошибок
  • CI пайплайн падает при высоких/критических CVE
  • Результаты появляются в security dashboard
  • Сканирования завершаются менее чем за 60 секунд

Продвинутые техники безопасности

Техника 1: Мульти-сканерный подход

Используйте несколько сканеров для комплексного покрытия:

#!/bin/bash
# multi_scan.sh - Запуск нескольких сканеров безопасности

IMAGE=$1
RESULTS_DIR="./security-results"
mkdir -p $RESULTS_DIR

echo "=== Запуск Trivy ==="
trivy image --format json -o $RESULTS_DIR/trivy.json $IMAGE

echo "=== Запуск Grype ==="
grype $IMAGE -o json > $RESULTS_DIR/grype.json

echo "=== Запуск Dockle ==="
dockle --format json -o $RESULTS_DIR/dockle.json $IMAGE

echo "=== Запуск Hadolint ==="
hadolint Dockerfile --format json > $RESULTS_DIR/hadolint.json

# Агрегация результатов
python3 aggregate_results.py $RESULTS_DIR

Скрипт агрегации результатов:

# aggregate_results.py
import json
import sys
from pathlib import Path

def aggregate_results(results_dir):
    results = {
        'critical': 0,
        'high': 0,
        'medium': 0,
        'low': 0,
        'config_issues': 0
    }

    # Парсинг результатов Trivy
    trivy_file = Path(results_dir) / 'trivy.json'
    if trivy_file.exists():
        with open(trivy_file) as f:
            trivy_data = json.load(f)
            for result in trivy_data.get('Results', []):
                for vuln in result.get('Vulnerabilities', []):
                    severity = vuln.get('Severity', '').lower()
                    if severity in results:
                        results[severity] += 1

    # Парсинг результатов Dockle
    dockle_file = Path(results_dir) / 'dockle.json'
    if dockle_file.exists():
        with open(dockle_file) as f:
            dockle_data = json.load(f)
            results['config_issues'] = len(dockle_data.get('details', []))

    print(f"Сводка по безопасности:")
    print(f"  Критические: {results['critical']}")
    print(f"  Высокие: {results['high']}")
    print(f"  Средние: {results['medium']}")
    print(f"  Проблемы конфигурации: {results['config_issues']}")

    # Выход с ошибкой если найдены критические/высокие
    if results['critical'] > 0 or results['high'] > 0:
        sys.exit(1)

if __name__ == '__main__':
    aggregate_results(sys.argv[1])

Техника 2: Генерация и анализ SBOM

Генерируйте Software Bill of Materials для compliance:

# Генерация SBOM с Trivy
trivy image --format spdx-json -o sbom.json myapp:latest

# Генерация с Syft (альтернатива)
syft myapp:latest -o spdx-json > sbom.json

# Сканирование SBOM на уязвимости
trivy sbom sbom.json

SBOM в CI/CD:

- name: Generate SBOM
  run: |
    trivy image --format spdx-json \
      -o sbom-${{ github.sha }}.json \
      myapp:${{ github.sha }}

- name: Upload SBOM as artifact
  uses: actions/upload-artifact@v3
  with:
    name: sbom
    path: sbom-*.json

- name: Attest SBOM
  uses: actions/attest-sbom@v1
  with:
    subject-name: ghcr.io/${{ github.repository }}
    subject-digest: ${{ steps.build.outputs.digest }}
    sbom-path: sbom-${{ github.sha }}.json

Техника 3: Применение политик с OPA

Определите кастомные политики безопасности:

# policy/container_security.rego

package container.security

# Запрет образов, работающих от root
deny[msg] {
    input.config.User == ""
    msg := "Контейнер не должен работать от root"
}

deny[msg] {
    input.config.User == "root"
    msg := "Контейнер не должен работать от root"
}

# Запрет образов с критическими уязвимостями
deny[msg] {
    vuln := input.vulnerabilities[_]
    vuln.Severity == "CRITICAL"
    msg := sprintf("Найдена критическая уязвимость: %s", [vuln.VulnerabilityID])
}

# Требование определённых меток
deny[msg] {
    not input.config.Labels["maintainer"]
    msg := "Образ должен иметь метку maintainer"
}

# Запрет привилегированных портов
deny[msg] {
    port := input.config.ExposedPorts[_]
    to_number(port) < 1024
    msg := sprintf("Открыт привилегированный порт: %s", [port])
}

Примеры из практики

Пример 1: Безопасность контейнеров в Shopify

Контекст: Shopify запускает тысячи контейнеров, обслуживающих миллионы продавцов.

Проблема: Высокая скорость деплоев (1000+ деплоев/день) делала ручные проверки безопасности невозможными.

Решение: Автоматизированные security gates в CI/CD:

  • Сканирование Trivy на каждом билде
  • Генерация и хранение SBOM
  • Автоматические комментарии к PR со сводкой уязвимостей
  • Жёсткие блокировки на критических CVE, мягкие предупреждения на высоких

Результаты:

  • 94% снижение уязвимостей, попадающих в продакшен
  • Среднее время сканирования: 23 секунды на образ
  • Ноль критических уязвимостей в продакшене за 18 месяцев
  • Осведомлённость разработчиков о безопасности выросла на 300%

Ключевой вывод: Сделайте безопасность быстрой и автоматической — если сканирование блокирует деплои, инженеры найдут способы обойти его.

Пример 2: Безопасные базовые образы Netflix

Контекст: Netflix управляет массивной контейнерной платформой в AWS.

Проблема: Сотни команд, выбирающих разные базовые образы, приводили к непоследовательной позиции безопасности.

Решение: Курируемый каталог базовых образов:

  • Предварительно hardened и pre-scanned базовые образы
  • Еженедельные автоматические обновления с патчами уязвимостей
  • Внутренний registry с подписанными, аттестованными образами
  • Применение политик, требующих одобренные базовые образы

Результаты:

  • 78% снижение уникальных CVE по всему парку
  • Цикл обновления базового образа сокращён с недель до часов
  • Доказательства compliance генерируются автоматически
  • Команды принимают безопасные настройки по умолчанию без усилий

Ключевой вывод: Переместите бремя безопасности на платформенные команды — предоставьте безопасные настройки по умолчанию, которые легко использовать.


Лучшие практики

Что делать

  1. Сканируйте рано и часто

    • Сканируйте во время билда, не только перед деплоем
    • Сканируйте в IDE с расширениями
    • Сканируйте на каждый PR
  2. Используйте минимальные базовые образы

    • Предпочитайте distroless или alpine
    • Удаляйте ненужные пакеты
    • Multi-stage builds для меньших образов
  3. Держите образы обновлёнными

    • Автоматизируйте обновления базовых образов
    • Пересобирайте при обновлении зависимостей
    • Планируйте регулярные пересборки
  4. Применяйте security gates

    • Блокируйте критические уязвимости
    • Требуйте одобрение security для исключений
    • Отслеживайте и устраняйте все проблемы

Чего избегать

  1. Не игнорируйте результаты сканера

    • Каждый алерт требует действия или документированного исключения
    • Ложные срабатывания должны подавляться правильно
    • Отслеживайте среднее время ремедиации
  2. Не запускайте от root

    • Всегда указывайте USER в Dockerfile
    • Используйте read-only файловые системы где возможно
    • Отбрасывайте ненужные capabilities

Советы экспертов

  • Совет 1: Используйте .trivyignore для принятых рисков — документируйте, почему каждый приемлем
  • Совет 2: Кэшируйте базы данных уязвимостей в CI для более быстрых сканирований
  • Совет 3: Настройте Dependabot или Renovate для автоматических обновлений базовых образов

Типичные ошибки и решения

Ошибка 1: Усталость от алертов из-за ложных срабатываний

Симптомы:

  • Команды игнорируют вывод сканера
  • Слишком много алертов низкой критичности
  • Реальные проблемы теряются в шуме

Причина: Отсутствие настройки конфигурации сканера.

Решение:

# .trivyignore - Документирование принятых рисков
# CVE-2023-xxxxx: Ложное срабатывание для нашего случая использования
# Принято: security-team
# Истекает: 2026-06-01
CVE-2023-xxxxx

# Подавление низкой критичности по умолчанию
# trivy.yaml
severity:

  - CRITICAL
  - HIGH

ignore-unfixed: true

Предотвращение: Начинайте только с высоких/критических; настраивайте по мере развития процессов.

Ошибка 2: Медленные сканирования блокируют CI

Симптомы:

  • Билды занимают слишком много времени
  • Разработчики пропускают сканирования безопасности
  • Ошибки таймаута в CI

Причина: Загрузка базы данных уязвимостей при каждом сканировании.

Решение:

# Кэширование базы данных Trivy в GitHub Actions
- name: Cache Trivy DB
  uses: actions/cache@v3
  with:
    path: ~/.cache/trivy
    key: trivy-db-${{ hashFiles('.github/workflows/security.yml') }}

- name: Download DB (if not cached)
  run: trivy image --download-db-only

- name: Scan (uses cached DB)
  run: trivy image --skip-db-update myapp:latest

Предотвращение: Всегда кэшируйте базу данных уязвимостей; обновляйте её отдельно по расписанию.


Инструменты и ресурсы

Рекомендуемые инструменты

ИнструментЛучше всего дляПлюсыМинусыЦена
TrivyВсё-в-одном сканированиеБыстрый, комплексный, бесплатныйМеньше guidance по ремедиацииБесплатно
SnykСоветы по ремедиацииОтличные предложения fix, интеграция IDEМедленнее, ограниченный бесплатный tierFreemium
GrypeЛёгкое сканированиеБыстрый, минимум зависимостейМеньше функций чем TrivyБесплатно
DockleLinting DockerfileПроверки бенчмарков CISТолько конфигурация, не CVEБесплатно
HadolintBest practices DockerfileЛовит типичные ошибкиОграниченный охватБесплатно

Критерии выбора

Выбирайте на основе:

  1. Скорость: Фокус на CI → Trivy или Grype
  2. Ремедиация: Нужен guidance по fix → Snyk
  3. Compliance: CIS бенчмарки → Dockle + Trivy

Дополнительные ресурсы


Безопасность контейнеров с помощью ИИ

Современные ИИ-инструменты улучшают безопасность контейнеров:

  • Приоритизация уязвимостей: ИИ ранжирует CVE по эксплуатируемости
  • Авто-ремедиация: Предложение и применение патчей автоматически
  • Обнаружение аномалий: Выявление подозрительного поведения контейнеров
  • Генерация конфигурации: Создание безопасных Dockerfile из требований

Инструменты: Snyk AI, Amazon Inspector, Google Cloud Security AI.


Framework принятия решений: Стратегия безопасности контейнеров

ФакторБазовый подходEnterprise подход
Частота сканированияТолько pre-deployКаждый билд + непрерывно
Выбор сканераTrivy (бесплатный)Trivy + Snyk (слоями)
Порог блокировкиТолько критическиеВысокие + Критические
Генерация SBOMОпциональноОбязательно с аттестацией
Применение политикРучной reviewАвтоматизировано с OPA

Измерение успеха

Отслеживайте эти метрики для оценки эффективности безопасности контейнеров:

МетрикаЦельИзмерение
Критические CVE в проде0Еженедельное сканирование registry
Среднее время ремедиации критических<24 часовАлерт → fix merged
Покрытие сканированием100%Отсканированные образы / задеплоенные
Процент ложных срабатываний<5%Подавленные / всего алертов
Влияние на время билда<60 секундДлительность сканера в CI
Возраст базового образа<30 днейДней с последней пересборки

Заключение

Ключевые выводы

  1. Сканируйте всё — каждый образ, каждый билд, каждый registry
  2. Используйте несколько сканеров — разные инструменты находят разные проблемы
  3. Автоматизируйте безжалостно — ручные security review не масштабируются
  4. Сделайте безопасность быстрой — медленные сканирования пропускают

План действий

  1. Сегодня: Запустите trivy image на самом критичном продакшен-образе
  2. На этой неделе: Добавьте сканирование Trivy в ваш CI пайплайн
  3. В этом месяце: Внедрите security gates, блокирующие уязвимые образы

См. также


Как ваша команда обеспечивает безопасность Docker-образов? Поделитесь своими стратегиями сканирования и полученными уроками в комментариях.

Официальные ресурсы