
Harbor: Docker Registry на своём сервере
Пошаговое руководство по установке и настройке Harbor — self-hosted Docker Registry с интеграцией сканера уязвимостей Trivy. Узнайте, как развернуть собственный реестр Docker-образов, настроить безопасность, управление проектами и автоматическую проверку контейнеров.
В одной из предыдущих статей, а именно в «Применение Portainer в CI/CD процессах», мы разобрались, что такое сборка Docker-образов и какие существуют варианты их хранения. В том примере использовался GitHub Docker Registry, а в своей работе я применяю хранилище в собственном Git-хостинге на базе Gitea.
Альтернативой хранению образов рядом с кодом является самостоятельный (self-hosted) репозиторий образов, например Harbor.
В этой статье мы разберём, что такое Harbor, как установить его на свой сервер и как начать им пользоваться.
Если вам нравятся подобные материалы, подписывайтесь на наш Telegram-канал «Код на салфетке»!
Что такое 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
и вносим изменения:
- Удаляем блок
ports
, чтобы прокси не слушал порт напрямую и был доступен только через Caddy. - Меняем значение
container_name
наharbor-proxy
— так будет проще ориентироваться. - В блок
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: https://github.com/proDreams/tempProject.
После внесения изменений отправляем коммит в репозиторий и ждём завершения сборки образа:

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

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

Заключение
Harbor — это мощное и удобное решение для организации собственного Docker Registry, которое подойдёт как для небольших команд, так и для крупных компаний. Я лично планирую перенести в него все свои образы и настроить гибкое распределение доступов.
Мир open-source решений постоянно развивается, и впереди ещё множество интересных инструментов, которые можно опробовать и внедрить в свои продакшн-процессы.
А если вы хотите узнавать о таких инструментах и лучших практиках их применения — присоединяйтесь к нашему Telegram-каналу «Код на салфетке»!
Все статьи