Search
Write a publication
Pull to refresh

Harbor: Docker Registry на своём сервере

Level of difficultyEasy
Reading time6 min
Views2.3K

В одной из предыдущих статей, а именно в «Применение Portainer в CI/CD процессах», мы разобрались, что такое сборка Docker-образов и какие существуют варианты их хранения. В том примере использовался GitHub Docker Registry, а в своей работе я применяю хранилище в собственном Git-хостинге на базе Gitea.

Альтернативой хранению образов рядом с кодом является самостоятельный (self-hosted) репозиторий образов, например Harbor.

В этой статье мы разберём, что такое Harbor, как установить его на свой сервер и как начать им пользоваться.


Что такое Harbor?

Harbor — это open-source решение для хранения Docker-образов на собственном сервере (self-hosted). Оно активно используется как в небольших проектах, так и в корпоративном сегменте. Дополнительно Harbor интегрируется с Trivy, который выполняет сканирование образов на наличие уязвимостей.

Ключевые особенности

  • UI и API для управления репозиториями образов.

  • RBAC — разграничение прав на уровне проектов, пользователей и групп.

  • Аутентификация и SSO (LDAP, OIDC, Keycloak и т.д.).

  • Поддержка различных типов артефактов — не только контейнеров, но и Helm-чартов, OCI-артефактов и других.

  • Встроенный прокси-кэш для зеркалирования внешних регистри.

  • Встроенный сканер уязвимостей (Trivy).

  • Репликация образов между несколькими инстансами Harbor.

  • Подпись и проверка образов через Notary.

  • Аудит-лог действий пользователей.

  • Многоуровневая политика хранения (retention policies).

Системные требования

Минимально

Рекомендовано

ЦПУ

2 CPU

4 CPU

ОЗУ

4 GB

8 GB

Диск

40 GB

160 GB

Что такое Trivy

Trivy — это open-source сканер уязвимостей и ошибок конфигурации (misconfig) от Aqua Security. Он умеет проверять:

  • Образы контейнеров — как ОС-пакеты, так и зависимости приложений (npm, pip, Go, Java, Ruby и т.д.).

  • Файловые системы и репозитории — ищет уязвимые зависимости прямо в коде проекта.

  • Kubernetes и IaC-манифесты — Helm, Kubernetes, Terraform и другие, на предмет небезопасных настроек.

  • SBOM — читает и генерирует SPDX/CycloneDX, а также сканирует зависимости по готовому SBOM-файлу.

  • Секреты — базовый поиск «утёкших» ключей и токенов в коде.

Как Trivy интегрирован в Harbor

Trivy в Harbor интегрирован как отдельный сервис-адаптер, который:

  • Сканирует образы вручную по запросу или автоматически при push (если включена эта функция).

  • Сохраняет отчёт по CVE с классификацией уязвимостей по уровням LOW / MEDIUM / HIGH / CRITICAL.

  • Позволяет задать политику блокировки pull (например, запрет на загрузку образов с уязвимостями уровня High и выше).

  • Поддерживает allowlist (игнор-лист) на уровне проекта.


Деплой Harbor

Приступим к установке Harbor на собственный сервер.

Что понадобится:

  • Домен второго или третьего уровня.

  • VPS, соответствующий системным требованиям.

  • Reverse-proxy — в моём случае это будет Caddy.

Конфигурация Harbor

Подключаемся к серверу по SSH, создаём директорию и переходим в неё:

mkdir harbor && cd harbor

Скачиваем установщик. Возьмём последнюю актуальную версию — 2.13.2:

curl -LO https://github.com/goharbor/harbor/releases/download/v2.13.2/harbor-online-installer-v2.13.2.tgz

Распаковываем архив и переходим в директорию:

tar xzf harbor-online-installer-v2.13.2.tgz && cd harbor

Переименовываем пример конфигурационного файла и открываем его для редактирования:

cp harbor.yml.tmpl harbor.yml && nano harbor.yml

Изменяем следующие параметры:

  • hostname — указываем домен без https://.

  • https — закомментируем весь блок, так как SSL-сертификат и обработку HTTPS в нашем случае будет обеспечивать Caddy.

  • external_url — раскомментируем параметр и укажем домен с префиксом https, например: https://<ваш_домен>

  • harbor_admin_password — зададим сложный пароль администратора Harbor.

  • database.password — укажем пароль для базы данных.

Остальные параметры можно оставить по умолчанию или адаптировать под свои нужды.

Сохраняем изменения (CTRL+S) и выходим из редактора (CTRL+X).

Запускаем генерацию конфигурационных файлов с включённым Trivy:

sudo ./prepare --with-trivy

На этом этапе будут загружены и подготовлены необходимые конфигурационные файлы.

Правки docker-compose.yml

Так как у меня Caddy работает в отдельном Docker Compose, Harbor нужно подключить к той же сети, что и Caddy.

Открываем файл для редактирования:

nano docker-compose.yml

В самом конце, в блоке networks, добавляем внешнюю сеть:

networks:
  harbor:
    external: false
  caddy_net:
    name: caddy_net
    external: true

Далее находим сервис proxy и вносим изменения:

  1. Удаляем блок ports, чтобы прокси не слушал порт напрямую и был доступен только через Caddy.

  2. Меняем значение container_name на harbor-proxy — так будет проще ориентироваться.

  3. В блок networks добавляем внешнюю сеть — в моём случае это caddy_net.

Настройка Caddy

Открываем Caddyfile и добавляем проксирование на nginx Harbor:

<ваш_домен> {
    encode {
        gzip
    }

    header {
        X-Content-Type-Options "nosniff"
    }

    reverse_proxy harbor-proxy:8080
}

Так Caddy будет обрабатывать входящие HTTPS-запросы и передавать их на Harbor.

Запуск

Для запуска выполняем команду:

docker compose up -d

Дожидаемся, пока скачаются образы и запустятся все контейнеры.

Когда Harbor будет запущен, открываем в браузере адрес вашего домена.

Если всё прошло успешно, вас встретит страница с формой входа — значит, установка завершена и сервис готов к работе.


Проект и отправка образа

Деплой прошёл успешно, теперь создадим проект и загрузим в него Docker-образ.

Что такое проект в Harbor?

В Harbor проект — это отдельное пространство для хранения артефактов (Docker-образов, Helm-чартов и др.), с собственными настройками доступа, политиками хранения и сканирования.

Проекты позволяют:

  • Разделять образы по приложениям, командам или окружениям (dev, staging, prod).

  • Настраивать права доступа для отдельных пользователей или групп.

  • Включать или отключать автоматическое сканирование уязвимостей.

  • Управлять retention-политикой (удаление старых или неиспользуемых образов).

Это удобно, когда в одном Harbor работают сразу несколько команд или сервисов.

Создание проекта

В левом меню переходим в раздел "Projects" — откроется страница со списком проектов.

По умолчанию уже есть проект library, но мы создадим свой. Нажимаем кнопку «New project».

В появившемся окне заполняем поля:

  • Название проекта — обязательно в нижнем регистре.

  • Уровень доступа — публичный или приватный.

  • Лимит дискового пространства — в гигабайтах или -1 для отключения лимита.

  • Переключатель Proxy Cache — при включении, если образа нет в вашем реестре, Harbor попытается получить его из другого источника и сохранить локально. Это удобно для часто используемых образов, но перед этим в разделе «Registries» нужно добавить источники.

После заполнения нажимаем «Ok» — проект появится в списке.

Переходим в созданный проект — откроется страница реестра с набором функций.

Чтобы получить подсказки по отправке образов, нажмите «PUSH COMMAND».

Здесь же указан адрес проекта в формате:

<ваш_домен>/<ваш_проект>/<название_образа>

Отправка образа в репозиторий

Для примера я воспользуюсь CI/CD-конфигурацией из статьи «Применение Portainer в CI/CD процессах».

Изначально у нас было так:

- name: Log in to GitHub Container Registry  
  uses: docker/login-action@v3  
  with:  
    registry: ghcr.io  
    username: ${{ github.actor }}  
    password: ${{ secrets.GITHUB_TOKEN }}  

- name: Build and push Docker image  
  uses: docker/build-push-action@v6  
  with:  
    context: .  
    push: true  
    cache-from: type=registry,ref=ghcr.io/prodreams/tempproject:latest  
    cache-to: type=inline  
    tags: |  
      ghcr.io/prodreams/tempproject:latest    
      ghcr.io/prodreams/tempproject:${{ github.sha }}

Чтобы отправлять образы в Harbor, нужно заменить адреса и реквизиты на новые:

- name: Log in to Harbor Registry  
  uses: docker/login-action@v3  
  with:  
    registry: <ваш_домен>/<ваш_проект>  
    username: ${{ secrets.HARBOR_USER }}  
    password: ${{ secrets.HARBOR_PASSWORD }}  

- name: Build and push Docker image  
  uses: docker/build-push-action@v6  
  with:  
    context: .  
    push: true  
    cache-from: type=registry,ref=<ваш_домен>/<ваш_проект>/tempproject:latest  
    cache-to: type=inline  
    tags: |  
      <ваш_домен>/<ваш_проект>/tempproject:latest    
      <ваш_домен>/<ваш_проект>/tempproject:${{ github.sha }}

Полный пример доступен в репозитории на GitHub: ссылка

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

Проверяем, что образ появился в репозитории Harbor:

Перейдя внутрь образа, можно запустить проверку на уязвимости (или включить автоматическую проверку в настройках проекта). В отчёте отобразятся все найденные уязвимости с указанием их уровня опасности:


Заключение

Harbor — это мощное и удобное решение для организации собственного Docker Registry, которое подойдёт как для небольших команд, так и для крупных компаний. Я лично планирую перенести в него все свои образы и настроить гибкое распределение доступов.

Мир open-source решений постоянно развивается, и впереди ещё множество интересных инструментов, которые можно опробовать и внедрить в свои продакшн-процессы.

А если вы хотите узнавать о таких инструментах и лучших практиках их применения — присоединяйтесь к нашему Telegram-каналу «Код на салфетке»!

Tags:
Hubs:
+14
Comments6

Articles