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 |
| Сканер конфигурации | Проблемы Dockerfile | Hadolint, 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 генерируются автоматически
- Команды принимают безопасные настройки по умолчанию без усилий
Ключевой вывод: Переместите бремя безопасности на платформенные команды — предоставьте безопасные настройки по умолчанию, которые легко использовать.
Лучшие практики
Что делать
Сканируйте рано и часто
- Сканируйте во время билда, не только перед деплоем
- Сканируйте в IDE с расширениями
- Сканируйте на каждый PR
Используйте минимальные базовые образы
- Предпочитайте
distrolessилиalpine - Удаляйте ненужные пакеты
- Multi-stage builds для меньших образов
- Предпочитайте
Держите образы обновлёнными
- Автоматизируйте обновления базовых образов
- Пересобирайте при обновлении зависимостей
- Планируйте регулярные пересборки
Применяйте security gates
- Блокируйте критические уязвимости
- Требуйте одобрение security для исключений
- Отслеживайте и устраняйте все проблемы
Чего избегать
Не игнорируйте результаты сканера
- Каждый алерт требует действия или документированного исключения
- Ложные срабатывания должны подавляться правильно
- Отслеживайте среднее время ремедиации
Не запускайте от 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 | Медленнее, ограниченный бесплатный tier | Freemium |
| Grype | Лёгкое сканирование | Быстрый, минимум зависимостей | Меньше функций чем Trivy | Бесплатно |
| Dockle | Linting Dockerfile | Проверки бенчмарков CIS | Только конфигурация, не CVE | Бесплатно |
| Hadolint | Best practices Dockerfile | Ловит типичные ошибки | Ограниченный охват | Бесплатно |
Критерии выбора
Выбирайте на основе:
- Скорость: Фокус на CI → Trivy или Grype
- Ремедиация: Нужен guidance по fix → Snyk
- 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 дней | Дней с последней пересборки |
Заключение
Ключевые выводы
- Сканируйте всё — каждый образ, каждый билд, каждый registry
- Используйте несколько сканеров — разные инструменты находят разные проблемы
- Автоматизируйте безжалостно — ручные security review не масштабируются
- Сделайте безопасность быстрой — медленные сканирования пропускают
План действий
- Сегодня: Запустите
trivy imageна самом критичном продакшен-образе - На этой неделе: Добавьте сканирование Trivy в ваш CI пайплайн
- В этом месяце: Внедрите security gates, блокирующие уязвимые образы
См. также
Как ваша команда обеспечивает безопасность Docker-образов? Поделитесь своими стратегиями сканирования и полученными уроками в комментариях.
