Docker в CI/CD: автосборка, сканирование образов (Trivy, Docker Scout), публикация

Рейтинг: 64.6% · 7 голосов
Практический курс по Docker: образы, контейнеры, тома, сети, Compose и продакшен. Уроки по главам с обсуждением.
Ответить
Аватара пользователя
Marina_DevOps
Сообщения: 25
Зарегистрирован: 11 май 2026, 05:31

Docker в CI/CD: автосборка, сканирование образов (Trivy, Docker Scout), публикация

Сообщение Marina_DevOps »

АкадемияDocker с нуляГлава 16 из 17
Оглавление курса (17)
  1. Что такое Docker и какие задачи он решает
  2. Установка Docker и запуск первого контейнера
  3. Образы: слои, теги и реестр Docker Hub
  4. Пишем свой Dockerfile
  5. Тома и хранение данных: volumes и bind mounts
  6. Сети в Docker: связываем контейнеры между собой
  7. Переменные окружения и конфигурация контейнеров
  8. Docker Compose: поднимаем многоконтейнерное приложение
  9. Оптимизация образов: multi-stage сборка, размер и кэш слоёв
  10. Логи, отладка и мониторинг контейнеров
  11. Базовая безопасность контейнеров
  12. Подготовка к продакшену: что важно учесть
  13. Dockerfile глубже: ENTRYPOINT и CMD, HEALTHCHECK, .dockerignore, запуск не от root
  14. Реестры образов: приватные registry, push и pull, теги и digest, imagePullSecrets
  15. BuildKit и buildx: multi-arch сборки, секреты сборки, экспорт кэша
  16. Docker в CI/CD: автосборка, сканирование образов (Trivy, Docker Scout), публикация (вы здесь)
  17. Итоговый проект и куда расти: от Dockerfile до прода, обзор оркестрации (Kubernetes, Podman, OCI)
Собирать образ руками и пушить его со своего ноутбука можно, пока команда состоит из одного человека. Дальше начинаются сюрпризы: кто-то забыл пересобрать, у кого-то локальный кэш дал другой результат, на проде внезапно крутится образ двухнедельной давности. Пайплайн закрывает эти вопросы. Схема одинаковая в любой CI-системе: checkout кода, сборка через buildx, сканирование на уязвимости, публикация с нормальными тегами.

Автосборка в GitHub Actions:

Возьмём GitHub Actions и публикацию в GHCR. Токен для реестра выдаёт сам раннер, отдельный секрет заводить не нужно. Файл .github/workflows/docker.yml:

Код: Выделить всё

name: docker
on:
  push:
    branches: [main]
    tags: ['v*']

permissions:
  contents: read
  packages: write

jobs:
  build:
    runs-on: ubuntu-24.04
    steps:
      - uses: actions/checkout@v5
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - id: meta
        uses: docker/metadata-action@v5
        with:
          images: ghcr.io/${{ github.repository }}
          tags: |
            type=sha
            type=semver,pattern={{version}}
      - id: build
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
metadata-action генерирует теги сам: пуш в main даёт sha-<короткий хэш коммита>, git-тег v1.4.2 превращается в тег образа 1.4.2. Получается то, к чему мы шли в главе 14: у каждого коммита свой неизменяемый тег, а деплоить можно по digest. Кэш type=gha (разбирали его в главе 15) сокращает повторную сборку с минут до десятков секунд. Блок permissions обязателен: без packages: write пуш в GHCR падает с 403, при отладке проверяйте его первым.

Сканирование образов, Trivy и Docker Scout:

Образ собрался, но внутри него базовый дистрибутив с пакетами, у которых есть известные CVE. Сканер сверяет состав образа с базами уязвимостей. Trivy полностью открытый и работает где угодно, Scout встроен в Docker CLI. Локально:

Код: Выделить всё

trivy image --severity HIGH,CRITICAL --ignore-unfixed myapp:1.4.2

docker scout quickview myapp:1.4.2
docker scout cves --only-severity critical,high myapp:1.4.2
quickview даёт сводку и подсказывает более свежий базовый образ, cves выводит список с версиями, в которых уязвимость закрыта. У Scout бесплатный тариф ограничен по числу репозиториев, поэтому в пайплайнах чаще живёт Trivy. Шаг в том же workflow, между сборкой и деплоем:

Код: Выделить всё

      - uses: aquasecurity/trivy-action@0.33.0
        with:
          image-ref: ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}
          severity: CRITICAL,HIGH
          ignore-unfixed: true
          exit-code: '1'
Сканер берёт образ по digest из вывода шага сборки, так проверяется ровно тот артефакт, который уехал в реестр. exit-code 1 роняет джоб, если нашлись непочиненные CRITICAL или HIGH. Флаг ignore-unfixed убирает шум: уязвимости без патча в апстриме вы пересборкой не почините. Конкретные ложные срабатывания заносите в файл .trivyignore, обязательно с комментарием и датой пересмотра, иначе через год никто не вспомнит, почему CVE замьючен.

GitLab CI и реалии СНГ:

В СНГ заметная часть команд сидит на self-hosted GitLab. Тот же конвейер на dind выглядит так:

Код: Выделить всё

stages: [build, scan]

build:
  stage: build
  image: docker:28
  services:
    - docker:28-dind
  variables:
    DOCKER_TLS_CERTDIR: "/certs"
  script:
    - echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
    - docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" .
    - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"

scan:
  stage: scan
  image:
    name: aquasec/trivy:0.65.0
    entrypoint: [""]
  variables:
    TRIVY_USERNAME: "$CI_REGISTRY_USER"
    TRIVY_PASSWORD: "$CI_REGISTRY_PASSWORD"
  script:
    - trivy image --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
Скан здесь идёт вторым джобом и тянет уже запушенный образ из реестра. Это рабочая модель, если считать реестр карантином: попадает в него всё, а деплой стартует только после зелёного скана. dind требует privileged-раннер, и безопасники это не любят, альтернатива buildx с драйвером kubernetes или удалённым builder.

И про доступность. Анонимные pull с Docker Hub жёстко лимитированы, а с части провайдеров СНГ внешние реестры периодически отваливаются. Базовые образы держите у себя: подойдут GitLab Dependency Proxy, Harbor с proxy-cache или Yandex Container Registry.

Типичные грабли:

Деплой по latest. Тег перезаписываемый, вы никогда не докажете, что именно крутится на проде. Деплойте по тегу с коммитом или по digest.

Секреты через build-arg. ARG с токеном остаётся в метаданных образа, docker history его покажет. Секреты передавайте только через RUN --mount=type=secret, как в главе 15.

Скан без гейта. Если push прошёл, а скан просто пишет отчёт в артефакты, дырявый образ уже доступен для деплоя. Либо сканируйте до push (в GitHub Actions соберите с load: true), либо блокируйте деплой результатом скана.

Кэш gha не резиновый: лимит 10 ГБ на репозиторий, старые слои вытесняются. Если сборка внезапно стала холодной, смотрите, что выело кэш.

Pull без логина в CI. Облачные раннеры ходят в Docker Hub с общих IP и быстро упираются в лимит. Логиньтесь даже там, где образы только тянутся.

Итог:

Честный минимум пайплайна: buildx с кэшем, Trivy с порогом по severity, публикация с неизменяемым тегом по коммиту и гейт на деплой. Этого хватает большинству команд. В следующей главе соберём итоговый проект целиком, от Dockerfile до продакшена, и посмотрим в сторону Kubernetes, Podman и стандартов OCI.
👍4 ❤️3 🔥1 😄 🤔
✔ Лучший ответ сформирован автоматически — stewartn
Marina_DevOps писал(а):Если push прошёл, а скан просто пишет отчёт в артефакты, дырявый образ уже доступен для деплоя. вот это у нас ровно так и работало почти год. отчеты складывались в артефакты и никто их не открыл ни разу. поставили exit-code 1, неделю чинили все подряд, зато теперь хоть понятно что едет на прод
Перейти к ответу →
Аватара пользователя
kuojuey
Сообщения: 2
Зарегистрирован: 15 май 2026, 05:38

Re: Docker в CI/CD: автосборка, сканирование образов (Trivy, Docker Scout), публикация

Сообщение kuojuey »

Прогнал trivy по нашему проду ради интереса. 63 HIGH и 12 CRITICAL, база python:3.9-slim не обновлялась с 2023 года. Сижу теперь с этим знанием и не знаю кому его продать)) ignore-unfixed реально спасает, без него простыня на три экрана и половина без фиксов
👍1 ❤️ 🔥2 😄 🤔
Аватара пользователя
stewartn
Сообщения: 1
Зарегистрирован: 08 июн 2026, 08:45

Re: Docker в CI/CD: автосборка, сканирование образов (Trivy, Docker Scout), публикация

Сообщение stewartn »

✔ Лучший ответ — сформирован автоматически
Marina_DevOps писал(а):Если push прошёл, а скан просто пишет отчёт в артефакты, дырявый образ уже доступен для деплоя.
вот это у нас ровно так и работало почти год. отчеты складывались в артефакты и никто их не открыл ни разу. поставили exit-code 1, неделю чинили все подряд, зато теперь хоть понятно что едет на прод
👍 ❤️ 🔥 😄 🤔1
Аватара пользователя
stelojen
Сообщения: 1
Зарегистрирован: 07 июн 2026, 02:19

Re: Docker в CI/CD: автосборка, сканирование образов (Trivy, Docker Scout), публикация

Сообщение stelojen »

а kaniko совсем все? у нас на гитлабе им до сих пор собирают, девопс который это настраивал уволился, трогать страшно
👍 ❤️2 🔥 😄 🤔
Аватара пользователя
fedya2024
Сообщения: 1
Зарегистрирован: 27 май 2026, 22:46

Re: Docker в CI/CD: автосборка, сканирование образов (Trivy, Docker Scout), публикация

Сообщение fedya2024 »

kaniko гугл заархивировал еще в 2025, обновлений и фиксов безопасности не будет. перевозите на buildx с kubernetes-драйвером или на buildah. мы переехали за пару вечеров, дольше всего кэш заново настраивали
👍2 ❤️ 🔥 😄 🤔
Ответить
← Предыдущая глава
BuildKit и buildx: multi-arch сборки, секреты сборки, экспорт кэша
Следующая глава →
Итоговый проект и куда расти: от Dockerfile до прода, обзор оркестрации (Kubernetes, Podman, OCI)

Все главы курса «Docker с нуля»

Поделиться темой: ✈ Telegram VK

Вернуться в «Docker с нуля»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость