Nexus Repository в Docker Compose: готовый файл
Когда в команде появляется больше одного языка и больше одного CI-пайплайна, начинается зоопарк: свой Docker registry, отдельный proxy для npm, кэш для Maven, где-то ещё PyPI-зеркало. Nexus Repository закрывает всё это одним сервисом — универсальным менеджером артефактов, который умеет проксировать внешние реестры, хранить свои сборки и раздавать их по HTTP. Ниже — рабочий docker-compose.yml и пошаговая настройка под Maven, npm, PyPI и Docker одновременно.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Зачем Nexus, если есть Docker Hub и npmjs напрямую
Прямые обращения к публичным реестрам работают, пока их не становится много. Проблемы начинаются предсказуемо:
- Rate limit. Docker Hub ограничивает анонимные и даже авторизованные pull'ы для бесплатных аккаунтов — в CI, который гоняет сборки десятки раз в день, лимит выбивается быстро.
- Нет единой точки для приватных артефактов. Свои Maven-библиотеки, npm-пакеты для внутреннего использования и Docker-образы с секретами внутри держать в публичных реестрах нельзя, а разносить по трём разным сервисам — лишняя инфраструктура.
- CI зависит от внешней сети. Если сборка тянет зависимости напрямую с npmjs.org или repo1.maven.org, любой сбой у них — это сбой у вас. Локальный proxy-кэш решает и это: один раз скачанный пакет отдаётся из кэша даже если апстрим недоступен.
Nexus Repository OSS (бесплатная версия от Sonatype) закрывает три сценария сразу: proxy (кэширующее зеркало внешнего реестра), hosted (собственное хранилище для ваших артефактов) и group (объединение нескольких репозиториев под одним URL — CI обращается в одно место, а Nexus сам решает, откуда отдать пакет).
Альтернатива для одного только Docker registry — поднять приватный Docker registry на VPS без лишнего функционала. Это проще и легче по ресурсам, но если нужны ещё Maven/npm/PyPI — придётся городить несколько сервисов вместо одного Nexus.
Что нужно серверу перед установкой
Nexus — не самый лёгкий сервис: это Java-приложение с собственной базой данных под капотом, и оно ощутимо ест память под индексы и кэш.
Ориентировочно, по документации Sonatype — от 2 vCPU и 4 GB RAM для небольшой команды, для активного CI с несколькими репозиториями комфортнее 8 GB RAM и SSD (артефакты и индексы дают заметную нагрузку на I/O). Точные цифры зависят от числа репозиториев и трафика — начните с 4 GB, смотрите потребление через docker stats и увеличивайте по необходимости.
Проверьте перед установкой:
# Docker и Compose plugin должны быть установлены
docker --version
docker compose version
# Свободное место — под артефакты и кэш нужно с запасом
df -h /var/lib/docker
# Официальный образ использует внутри UID 200 — не критично для named volume,
# но важно, если будете подключать директорию с хоста
Если Docker ещё не установлен, есть отдельная инструкция по установке Docker с нуля на Ubuntu 24.04.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверГотовый docker-compose.yml
Минимальная рабочая конфигурация с именованным volume для данных, ограничением памяти и healthcheck:
services:
nexus:
image: sonatype/nexus3:latest
container_name: nexus
restart: unless-stopped
environment:
- INSTALL4J_ADD_VM_PARAMS=-Xms1200m -Xmx1200m -XX:MaxDirectMemorySize=2g
- NEXUS_SECURITY_RANDOMPASSWORD=false
volumes:
- nexus-data:/nexus-data
ports:
- "127.0.0.1:8081:8081" # веб-интерфейс и API
- "127.0.0.1:8082:8082" # hosted Docker-репозиторий (создадим ниже)
mem_limit: 3g
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8081/service/rest/v1/status"]
interval: 30s
timeout: 10s
retries: 5
start_period: 180s
volumes:
nexus-data:
Пояснения по конфигу:
INSTALL4J_ADD_VM_PARAMS— это параметры JVM.Xms/Xmxфиксируют размер heap (не даём JVM разрастаться бесконтрольно),MaxDirectMemorySize— под off-heap буферы, которые Nexus активно использует для работы с блобами. Значения ниже подберите под вашmem_limit: суммарно heap + direct memory + служебные накладные расходы JVM должны укладываться в лимит контейнера с запасом.- Порты забиндены на
127.0.0.1— снаружи Nexus не должен торчать напрямую, доступ наружу даём через reverse proxy с TLS (см. ниже). Это разумная практика для любого сервиса с Docker-сетями — минимизировать поверхность атаки. nexus-data— именованный volume, туда пишутся артефакты, база данных, конфиги и логи. Про разницу между volume и bind mount и когда что использовать — отдельный разбор в статье про типы Docker volumes.start_period: 180sв healthcheck — не занижайте, Nexus реально стартует по 1.5–3 минуты на первом запуске (создаёт схему БД и индексы), и преждевременный "unhealthy" статус ничего не значит.
Запуск:
docker compose up -d
docker compose logs -f nexus # ждём строку "Started Sonatype Nexus"
Первый запуск и базовая настройка
После старта веб-интерфейс доступен на http://127.0.0.1:8081 (или через SSH-туннель, если порт закрыт наружу). Логин администратора — admin, пароль генерируется автоматически и лежит в volume:
docker compose exec nexus cat /nexus-data/admin.password
Дальше мастер настройки попросит:
- Сменить пароль администратора на постоянный.
- Решить, разрешать ли анонимный доступ на чтение (для внутреннего сервиса за reverse proxy обычно лучше отключить — доступ только по авторизации).
После этого создайте отдельных пользователей или роли для CI — не гоняйте пайплайны под admin. В Security → Users создайте технического пользователя, например ci-bot, и выдайте ему роль nx-repository-view-*-*-* только на нужные репозитории, а не полный доступ.
Пароли для этого пользователя и токены CI храните не в открытом виде в репозитории — если у вас Docker secrets в других сервисах на этом же сервере, подход к безопасному хранению паролей разобран в статье про Docker secrets.
Репозитории: Maven, npm, PyPI и Docker в одном Nexus
Создаются они в Repository → Repositories → Create repository, для каждого типа своя логика.
Maven. По умолчанию Nexus уже создаёт maven-central (proxy на repo1.maven.org), maven-releases и maven-snapshots (hosted для ваших сборок) и maven-public (group, объединяющий все три). В settings.xml проекта или CI-раннера достаточно одного mirror:
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>https://nexus.example.com/repository/maven-public/</url>
</mirror>
npm. Создайте npm-proxy (Remote storage: https://registry.npmjs.org), npm-hosted для внутренних пакетов и npm-group, объединяющий оба. На стороне разработчиков и CI:
npm config set registry https://nexus.example.com/repository/npm-group/
PyPI. Аналогично — pypi-proxy (https://pypi.org), при желании pypi-hosted, и группа. Для pip:
# pip.conf
[global]
index-url = https://nexus.example.com/repository/pypi-group/simple
Docker. Тип репозитория docker создаётся отдельно от Maven/npm — у него свой HTTP-порт (в нашем compose это 8082), потому что Docker registry API работает не через путь, а ожидает отдельный listener. При создании укажите:
- Repository Connectors → HTTP → порт
8082(совпадает с тем, что открыли в docker-compose.yml); - Enable Docker V1 API — обычно не нужно, оставьте выключенным;
- Realm: в Security → Realms включите Docker Bearer Token Realm — без него
docker loginне заработает.
Для доступа снаружи по HTTPS нужен reverse proxy — Nginx или Traefik перед Docker-контейнерами, с проксированием на порт 8082 и корректной передачей заголовков (Docker registry API чувствителен к Host и требует поддержки chunked transfer для загрузки слоёв большого размера). Минимальный пример для Nginx:
server {
listen 443 ssl http2;
server_name registry.example.com;
client_max_body_size 0; # слои образов бывают большими
location / {
proxy_pass http://127.0.0.1:8082;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900s;
}
}
После этого docker login registry.example.com и docker push registry.example.com/my-app:1.0 работают как с любым приватным реестром — только с бонусом в виде Maven, npm и PyPI рядом, в одном интерфейсе.
Бэкап, обновление и типичные грабли
Бэкап. Простейший вариант — остановить контейнер и заархивировать volume:
docker compose stop nexus
docker run --rm -v nexus_nexus-data:/data -v $(pwd):/backup alpine \
tar czf /backup/nexus-backup-$(date +%F).tar.gz -C /data .
docker compose start nexus
Для продакшена лучше настроить в самом Nexus задачу Admin → Tasks → Create task → Export databases for backup по расписанию, а архивировать volume с остановкой сервиса — раз в сутки ночью, когда простой минимально заметен.
Обновление. Меняете тег образа, поднимаете заново — Nexus сам мигрирует схему при старте на новой версии. Перед мажорным апгрейдом обязательно делайте бэкап volume: откат версии образа без бэкапа данных может не сработать, если между версиями менялся формат хранения.
Грабля №1 — диск кончается незаметно. Nexus по умолчанию хранит в blob store вообще всё, что когда-либо проксировал, без ограничения по времени. Настройте Cleanup Policies (Repository → Cleanup Policies) с условием по возрасту или количеству версий и привесьте их к proxy-репозиториям — иначе кэш Maven Central за полгода активного CI может занять десятки гигабайт.
Грабля №2 — не освобождается место после удаления. Удаление компонента из репозитория само по себе не сжимает blob store — файлы помечаются как soft-deleted. Нужна отдельная задача Compact blob store, запускайте её после чистки вручную или по расписанию.
Грабля №3 — docker login падает с 401. В 9 случаях из 10 причина — не включённый Docker Bearer Token Realm (см. раздел выше) или reverse proxy, который не пробрасывает заголовки авторизации. Проверить можно прямым запросом к API, минуя proxy: curl -u admin:pass http://127.0.0.1:8082/v2/.
Грабля №4 — OutOfMemory при росте числа репозиториев. Если Xmx выставлен слишком низко относительно нагрузки от CI, JVM падает по OOM. Смотрите docker compose logs nexus на OutOfMemoryError и поднимайте Xmx вместе с mem_limit пропорционально.
Если Nexus разворачивается как часть CI/CD-инфраструктуры вместе с раннерами, полезно свериться со статьёй про настройку GitLab CI/CD на VPS — там разобрано, как подружить раннер с приватными реестрами через переменные окружения.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Чем Nexus OSS отличается от платной версии Nexus Pro?
OSS не имеет ограничений по числу репозиториев или пользователей, но лишён высокой доступности (кластера), продвинутого аудита, интеграции с внешними системами контроля версий на уровне Pro-фич и части enterprise-поддержки. Для одного сервера и одной команды OSS обычно хватает с запасом.
Стоит ли выбрать Nexus вместо Harbor для Docker registry?
Если нужен только Docker registry — Harbor заточен под это лучше: встроенное сканирование образов на уязвимости, репликация между инстансами из коробки. Если же кроме Docker нужны Maven/npm/PyPI в одном месте — Nexus выигрывает за счёт универсальности. Подробности по альтернативе — в статье про установку Harbor на VPS.
Можно ли запустить несколько Docker-репозиториев с разными портами?
Да, каждый hosted или proxy Docker-репозиторий в Nexus может слушать свой HTTP-порт — просто пробросьте нужное количество портов в docker-compose.yml и настройте соответствующие connectors в интерфейсе.
Нужен ли внешний PostgreSQL или хватит встроенной базы?
Для одного сервера и умеренной нагрузки встроенного хранилища достаточно. Внешняя БД имеет смысл при масштабировании на несколько нод Nexus Pro с общим состоянием — для одиночного OSS-инстанса это избыточно.
Как перенести Nexus на другой сервер?
Остановить контейнер, скопировать содержимое volume nexus-data на новый сервер (rsync или tar, как в разделе про бэкап), поднять тот же docker-compose.yml на новом месте. IP и домен репозиториев в конфигах клиентов (settings.xml, .npmrc, pip.conf) поменять на новый адрес.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →