Представьте, что ваша команда каждое утро тратит лишние полчаса, ожидая загрузки контейнеров из Интернета. Звучит знакомо? В современном мире разработки скорость и автономность инфраструктуры становятся решающими факторами. Особенно остро это почувствовали российские компании в 2024 году, когда из-за санкционных ограничений доступ к Docker Hub внезапно пропал для целой страны.
В материале рассказали, как развернуть собственный приватный Docker-репозиторий на базе белорусского VPS, чтобы ваши образы хранились под полным контролем, а команда разработчиков работала быстрее и увереннее.
Зачем нужен приватный Docker-репозиторий
Когда у вас десятки микросервисов и регулярные релизы, полагаться только на публичный Docker Hub становится рискованно. Во-первых, это медленно. Каждый docker pull тянет сотни мегабайт через внешний канал. Во-вторых, централизованный публичный сервис может стать недоступным в самый неподходящий момент, как это уже произошло, пусть и ненадолго. Собственный же Docker-репозиторий решает сразу несколько задач. Ваши образы хранятся в локальной инфраструктуре, что значительно ускоряет их загрузку.
Дополнительно повышается безопасность. Чужие люди не получат доступ к вашим контейнерам, а конфиденциальный код останется внутри компании. Вы сами контролируете доступ. Можно завести учётные записи для членов команды и ограничить права, никто лишний не пушнет образ в продакшен случайно.
Многие дата-центры, особенно в Беларуси, берут плату за внешний трафик, и постоянное скачивание образов из глобального Интернета обходится недёшево. Если же репозиторий находится на вашем сервере, внутри той же сети, вы практически не тратите внешний канал и получаете максимальную скорость загрузки. В корпоративной среде подобное решение зачастую диктуется правилами: политика безопасности может требовать полного контроля над артефактами в CI/CD. Неудивительно, что после истории с Docker Hub многие компании в России и СНГ перешли на собственные registry или отечественные аналоги.
Результат? Ускоренные сборки, довольные разработчики и уверенность, что ваш процесс деплоя не встанет из-за внешних проблем. Кстати, умение работать с контейнерной инфраструктурой сегодня ценится на вес золота. Навык настройки приватного Docker-репозитория не только облегчит жизнь вашей команде, но и станет плюсом в вашем профессиональном портфолио.
Выбор белорусского VPS и подготовка сервера
Белорусские дата-центры славятся стабильной работой и близостью к российским сетям. Задержки минимальны, а надёжность на высоте. Многие провайдеры в Минске и других городах предлагают тарифы с гибкой конфигурацией, оплатой в российских рублях и дружелюбной поддержкой. Например, аренда небольшого VPS в Беларуси (2 CPU, 4 ГБ RAM, SSD) обойдётся порядка 1000-1500 ₽ в месяц, что по карману даже стартапу. При этом часто включён безлимитный трафик внутри сети, а на внешний канал даётся щедрый пакет или вовсе безлимит в некоторых тарифах. Так что для хранения Docker-образов такой вариант отлично подходит. Вы платите фиксированную сумму в рублях, а взамен получаете стабильный сервер поблизости от вашей команды.
Для старта работы вам понадобится виртуальный сервер под управлением современной Linux-системы. Отлично подойдёт Ubuntu LTS либо Debian.. Рекомендуемые минимальные ресурсы: 2 ГБ оперативной памяти и около 20 ГБ свободного места на диске. Этого хватит для самого реестра и хранения пары десятков образов. Если образы тяжёлые или их сотни, сразу закладывайте больше пространства. Процесс подготовки сервера включает несколько шагов.
Установка Docker
Подключитесь к своему VPS по SSH и обновите систему:
sudo apt update && sudo apt upgrade -y
Затем установите Docker Engine. На Ubuntu это делается парой команд. Добавьте ключ и репозиторий Docker, после чего через apt поставьте пакеты docker-ce, docker-ce-cli, containerd.io и плагин docker-compose. Docker достаточно установить в стандартной конфигурации, он сразу готов к работе. Не забудьте добавить своего пользователя в группу docker командой:
sudo usermod -aG docker $USER
Чтобы запускать Docker без sudo, и перезагрузитесь или перелогиньтесь. Включите Docker в автозапуск:
sudo systemctl enable docker && sudo systemctl start docker
Теперь база готова, ваш сервер умеет запускать контейнеры.
Подготовка структуры для реестра
Создайте на сервере отдельные директории, где Docker Registry будет хранить данные. Например, удобно собрать всё в каталоге /opt/docker-registry. Внутри него понадобятся папки: data для образов, certs для TLS-сертификатов, auth для файлов авторизации и config для конфигурации реестра. Создайте их одной командой:
sudo mkdir -p /opt/docker-registry/{data,auth,certs,config}
sudo chown -R $USER:$USER /opt/docker-registry
Задайте права доступа так, чтобы текущий пользователь мог работать с этими файлами. Если вы работаете под root, права можно не менять. Структура подготовлена, пора переходить к настройке сервиса реестра.
Настройка приватного Docker-реестра
Теперь создайте Docker Registry и настройте защиту. Контейнерный реестр — это веб-сервис, значит, нужны HTTPS и пароли. Без шифрования Docker-клиент не станет пушить образы на сервер, поэтому сразу настройте безопасное соединение.
Получение SSL-сертификата
Для продакшена возьмите бесплатный сертификат Let’s Encrypt. Сначала зарегистрируйте домен, направьте DNS-запись типа A на IP вашего VPS. Например, пусть реестр будет по адресу docker.myteam.by. После этого установите Certbot:
sudo apt install -y certbot
sudo certbot certonly --standalone -d docker.myteam.by
Certbot поднимет временный веб-сервер и получит сертификаты, которые появятся в /etc/letsencrypt/live/docker.myteam.by/. Скопируйте fullchain.pem как registry.crt и privkey.pem как registry.key в /opt/docker-registry/certs/, назначьте владельцем своего пользователя. Сертификат Let’s Encrypt действует около трёх месяцев, настройте автопродление через cron или systemd.timer.
Если реестр используется только в локальной сети, можно сделать самоподписанный сертификат:
openssl req -newkey rsa:4096 -nodes -sha256 \
-keyout /opt/docker-registry/certs/registry.key \
-x509 -days 365 -out /opt/docker-registry/certs/registry.crt
Укажите Common Name равным хостнейму или IP-адресу. Такой сертификат действует год, но Docker не доверяет ему по умолчанию. Чтобы подключаться, добавьте сертификат в доверенные на машинах разработчиков или запустите Docker-демон с параметром –insecure-registry. Для продакшена лучше использовать Let’s Encrypt.
Настройка аутентификации
Реестр без паролей — рискованный вариант, любой сможет пушить и удалять образы. Добавьте базовую HTTP-аутентификацию через htpasswd. Установите утилиту:
sudo apt install -y apache2-utils
htpasswd -Bbn myuser StrongPassword123 > /opt/docker-registry/auth/htpasswd
Если нужны новые пользователи, добавляйте их так:
htpasswd -Bn другой_юзер >> /opt/docker-registry/auth/htpasswd
Файл хранит хешированные пароли в формате bcrypt. Берегите его, это ключ ко всем вашим образам.
Запуск Docker Registry в контейнере
Все приготовления завершены, пора запускать приватный реестр. Сам Docker распространяет образ registry со своим официальным Registry-сервером. Мы воспользуемся именно им, чтобы не изобретать велосипед.
Конфигурация и запуск реестра
Настроить Docker Registry можно либо параметрами окружения, либо файлом config.yml. Для наглядности создадим конфиг. Откройте файл /opt/docker-registry/config/config.yml в вашем любимом редакторе и пропишите в нём минимальные параметры:
version: 0.1
storage:
filesystem:
rootdirectory: /var/lib/registry
delete:
enabled: true # позволяем удаление образов
http:
addr: :5000
tls:
certificate: /certs/registry.crt
key: /certs/registry.key
auth:
htpasswd:
realm: "Registry Realm"
path: /auth/htpasswd
Здесь вы указываете, что хранилище образов будет в локальной файловой системе и разрешаете операцию удаления образов. HTTP-сервис будет слушать порт 5000 и сразу использовать ваш SSL-сертификат и ключ. Блок auth.htpasswd включает базовую аутентификацию: вы задали realm (произвольная строка, при желании) и путь к вашему файлу паролей внутри контейнера. Сохраните этот конфиг.
Теперь можно запустить контейнер реестра. Для удобства создайте Docker Compose файл. В /opt/docker-registry/docker-compose.yml разместите такой сервис:
version: '3.8'
services:
registry:
image: registry:2
container_name: my-docker-registry
restart: unless-stopped
ports:
- "5000:5000"
volumes:
- ./data:/var/lib/registry
- ./certs:/certs:ro
- ./auth:/auth:ro
- ./config/config.yml:/etc/docker/registry/config.yml:ro
Вы обозначили, что запускаете контейнер из образа registry:2. Вместо конкретной версии можно указать registry:2.8.3 или новее, но тег 2 обычно всегда указывает на последний релиз второй версии. Пробрасываете порт 5000 наружу, монтируете ваши подготовленные папки: каталоги с данными, сертификатами, файлом паролей и конфигом внутрь контейнера. Флаги :ro (read-only) на монтировании certs, auth и config гарантируют, что контейнер не поменяет наши файлы. После этого из директории /opt/docker-registry выполните запуск:
docker compose up -d
Контейнер registry стартует в фоновом режиме. Несколько секунд, и ваш приватный реестр уже работает на VPS! По идее, сейчас он уже готов принимать запросы по HTTPS на порт 5000. Но для удобства использования нужно настроить ещё финальный штрих.
Настройка обратного прокси
Если вы планируете пользоваться реестром с разных машин, удобнее всего сделать так, чтобы он был доступен по стандартному порту 443 с красивого URL. Для этого можно поставить nginx и настроить прокси на ваш сервис. Установите nginx командой:
sudo apt install -y nginx
И создайте конфигурацию в файле /etc/nginx/sites-available/registry:
upstream docker-registry {
server localhost:5000;
}
server {
listen 443 ssl;
server_name docker.myteam.by;
ssl_certificate /opt/docker-registry/certs/registry.crt;
ssl_certificate_key /opt/docker-registry/certs/registry.key;
location / {
proxy_pass http://docker-registry;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Эта конфигурация принимает соединения на порту 443 и пробрасывает все запросы на ваш контейнерный реестр, который слушает на 5000. По сути, nginx тут выполняет две роли: завершающий TLS и удобный роутер. В данном минимальном варианте вы весь трафик docker.myteam.by отдаёте registry, но можно более тонко настроить пути, если параллельно захотите повесить веб-интерфейс. Активируйте этот сайт:
sudo ln -s /etc/nginx/sites-available/registry /etc/nginx/sites-enabled/ && sudo nginx -t && sudo systemctl restart nginx
Теперь ваш реестр доступен напрямую по адресу https://docker.myteam.by без указания порта.
Обратный прокси не обязателен, Docker-клиент прекрасно умеет работать и с нестандартным портом. Однако наличия домена и порта 443 часто требуют корпоративные политики и просто это удобнее.
Использование репозитория командой и интеграция в CI
Итак, приватный Docker Registry поднят. Как же подключить к нему команду разработчиков? На самом деле Docker-клиенту всё равно, где хранится образ, на Docker Hub или на вашем сервере, лишь бы был доступ по адресу. Чтобы залогиниться в новый реестр, разработчикам нужно выполнить команду:
docker login docker.myteam.by
Docker запросит имя пользователя и пароль. Вводите те самые, что вы добавляли через htpasswd. Если данные верны, клиент напишет Login Succeeded. С этого момента можно пушить образы. Процесс почти не отличается от работы с Docker Hub, меняется только имя образа. Допустим, у вас уже собран локально образ frontend:latest. Перед отправкой его в приватный реестр нужно ретегировать с указанием нового репозитория:
docker tag frontend:latest docker.myteam.by/myproject/frontend:latest
docker push docker.myteam.by/myproject/frontend:latest
Вы указали имя репозитория docker.myteam.by/myproject/frontend — таким образом, образ отправится на ваш сервер и будет сохранён в приватном репозитории myproject/frontend. Вы можете придумать любую структуру имён, обычно первые сегменты до слеша служат как пространство проектов или команд. Например, каждый проект внутри компании может получать свой префикс в реестре. Когда образ запушен, его могут скачать другие разработчики или серверы. Для проверки удалите локальный образ docker rmi docker.myteam.by/myproject/frontend:latest и попробуйте скачать его заново:
docker pull docker.myteam.by/myproject/frontend:latest
Если увидите статус скачивания слоёв и успех, значит всё работает! Теперь все разработчики команды могут использовать этот репозиторий для обмена образами. Важно, что доступ имеет только ограниченный круг лиц. Если кто-то уволился или сторонний человек не должен больше тянуть образы, просто удалите или поменяйте его пароль в htpasswd.
Советы по эксплуатации и развитие решения
Вы получили полностью рабочий приватный Docker-репозиторий на своём сервере. Поздравляем, вы сделали весомый шаг к автономности инфраструктуры! Теперь несколько рекомендаций, чтобы система работала как часы.
Регулярно проверяйте, сколько места осталось в хранилище (/opt/docker-registry/data). Большой реестр может неожиданно заполнить диск, особенно если образы тяжёлые и часто обновляются. Настройте мониторинг дискового пространства и метрик самого реестра, например, Docker Registry умеет отдавать метрики для Prometheus. Не забывайте делать бекапы наиболее критичных образов, банально копировать каталог data или настроить выгрузку в облачное хранилище. В случае сбоя сервера вы быстро развернётесь на новом месте, не теряя артефактов.
Со временем в репозитории накапливается мусор. Образов становится десятки версий, часть уже не нужна. Вы включили опцию удаления (delete.enabled:true), но просто удалить тег через API недостаточно, слои останутся занимать место. Docker Registry поддерживает garbage collection, специальную процедуру очистки не ссылающихся слоёв. Чтобы ей воспользоваться, нужно временно остановить контейнер реестра и выполнить команду внутри него registry garbage-collect. Проще написать скрипт. Остановите ваш сервис (docker compose stop registry), запустите
docker run --rm -v /opt/docker-registry/data:/var/lib/registry registry:2 garbage-collect /etc/docker/registry/config.yml
и снова стартуйте реестр. Этот скрипт можно добавить в cron, скажем, раз в неделю ночью, чтобы пространство автоматически освобождалось.
Следите за обновлениями образа registry. Разработчики Docker время от времени выпускают новые версии, исправляют баги и уязвимости. Обновить просто, достаточно поменять тег образа в docker-compose.yml на свежий, например, registry:2.9 вместо registry:2.8.3, и перезапустить контейнер. Не забывайте обновлять и SSL-сертификат, если он самоподписанный или от Let’s Encrypt. Также, если уходит сотрудник, меняйте пароли или удаляйте его учётку из htpasswd сразу.
Наше решение отлично подходит для старта и небольших команд. Если ваша компания растёт и количество образов стремительно увеличивается, можно задуматься о более продвинутых решениях. Одно из них — Harbor, открытая платформа от VMware для управления образами. Harbor по сути надстройка над Docker Registry, у него есть веб-интерфейс, тонкие настройки доступа, сканирование уязвимостей, репликация между несколькими реестрами и прочие фишки. Многие крупные организации сразу выбирают Harbor вместо чистого Registry, и вы тоже сможете на него перейти, если базового функционала станет не хватать.
Заключение
Создание приватного Docker-репозитория на белорусском VPS — это инвестиция в независимость и скорость вашей разработки. Да, придётся потратить пару часов на настройку и затем регулярно администрировать сервис. Зато ваша команда перестанет зависеть от внешних облаков и чужих правил. Вы сами хозяин своих образов. Как говорится, лучший реестр тот, о существовании которого вы не вспоминаете, потому что он просто работает. Теперь это про ваш случай. Ваши разработчики смогут быстрее доставлять код в продакшен, а бизнес будет получать новые фичи без задержек.
Ценим тех, кто надолго
При оплате на год мы добавим ещё месяц.