В какой-то момент почти у любого проекта с Docker, CI и кучей зависимостей возникает одинаковая боль: сборки идут долго, внешние репозитории периодически тормозят, а половина трафика уходит на скачивание одних и тех же образов и пакетов.
Решение довольно приземлённое: поднять на отдельном VDS локальный «кеш-хаб» для всего, что чаще всего тянет ваш CI и разработчики:
- локальный Git-репозиторий (зеркало или главный origin);
- Docker registry mirror (кеширующее зеркало Docker Hub/других реестров);
- кеш для apt (для Debian/Ubuntu);
- npm proxy (кеширующий прокси для npm/yarn/pnpm).
В этой статье покажу, как спроектировать такую схему и базово настроить её на VDS, чтобы ускорить сборки и уменьшить зависимость от внешнего интернета.
Зачем нужен локальный кеш на VDS
Даже если у вас быстрый канал, внешние реестры и репозитории могут вести себя нестабильно. Любой «hiccup» npmjs или Docker Hub в рабочее время — подарочек в виде красных джобов в CI и нервного продакта.
Локальный кеш на VDS решает несколько задач одновременно:
- Скорость: повторные сборки и деплой занимают заметно меньше времени.
- Стабильность: внешние сервисы могут временно лежать, а ваши образы и пакеты уже закешированы.
- Контроль: можно регулировать политики хранения, чистки и доступов.
- Прозрачность: для CI и разработчиков всё выглядит почти как раньше — меняется только URL.
Ключевая идея: вы не строите «офлайновое зеркало всего мира», а кешируете только то, что реально использует ваш проект.
Архитектура: как связать Git, Docker, apt и npm на одном VDS
Базовая архитектура для небольшого до среднего проекта может выглядеть так:
- один VDS с публичным IP;
- на нём — небольшой reverse-proxy (например, Nginx) и несколько бэкендов;
- Git-сервер (например, Gitea/Gitolite/«голый» Git по SSH);
- Docker registry (кеширующий mirror, либо полноценный реестр с кешированием);
- apt-cache (прокси для репозиториев Debian/Ubuntu, например Apt-Cacher-NG или Squid);
- npm proxy (Sonatype Nexus, Verdaccio или аналог).
В CI и на dev-машинах вы прописываете этот VDS как:
- Git origin/fetch URL (ssh или https);
- registry для Docker:
registry.internal.exampleилиvds.example:5000; - HTTP-прокси для apt;
- registry/proxy для npm:
npm.internal.example.
Остальной мир (GitHub, Docker Hub, registry.npmjs.org, официальные apt-зеркала) становится «аплинком», которым занимается ваш кеш-хаб.

Git на VDS: структура репозиториев и доступы
Git здесь выполняет две роли:
- центральный origin для команды (если вы не на GitHub/GitLab SaaS);
- зеркало внешнего репозитория, с которого CI забирает код по локальной сети.
Вариант 1: VDS как основной Git-сервер
Если вы хотите полный контроль, поднимайте на VDS Git-сервер (например, Gitea) и настраивайте CI и разработчиков на него. Базовая схема:
- создать git-пользователя на VDS;
- создать bare-репозиторий;
- подключить CI по SSH или HTTPS.
# создаём пользователя для git
sudo adduser --disabled-password --gecos "" git
# создаём директорию под репозитории
sudo mkdir -p /srv/git/example.git
sudo chown -R git:git /srv/git
# инициализация bare-репозитория
sudo -u git git init --bare /srv/git/example.git
Дальше разработчики настраивают remote:
git remote add origin git@vds.example:/srv/git/example.git
CI в таком случае клонирует репозиторий с VDS локально, без обращения к внешним сервисам.
Вариант 2: VDS как зеркало GitHub/GitLab
Если основной репозиторий всё же на GitHub или GitLab, можно держать на VDS read-only зеркало для CI, чтобы ускорить клон и не зависеть от проблем внешних Git-сервисов:
# создаём bare-зеркало
sudo -u git git clone --mirror git@github.com:org/project.git /srv/git/project.git
# периодическая синхронизация (через cron или systemd timer)
cd /srv/git/project.git
sudo -u git git remote update
В CI прописываете URL этого зеркала. Даже если исходный репозиторий слегка тормозит, клон произойдёт из локального зеркала, а обновления подтянутся чуть позже.
Docker registry mirror на VDS
Docker-образы — один из крупнейших потребителей трафика в CI/CD. Небольшой Docker registry mirror на VDS кардинально меняет ситуацию: популярные образы подтягиваются из кеша, а не из интернета.
Минимальная конфигурация Docker registry как кеша
Разворачиваем registry в режиме pull-through cache. Пример конфига config.yml для кеша Docker Hub:
version: 0.1
log:
level: info
storage:
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :5000
proxy:
remoteurl: https://registry-1.docker.io
Запуск через Docker:
docker run -d --name registry-mirror -p 5000:5000 -v /opt/registry/config.yml:/etc/docker/registry/config.yml -v /opt/registry/data:/var/lib/registry registry:2
Теперь ваш VDS выступает кеширующим реестром. Чтобы Docker-клиенты использовали его как mirror Docker Hub, на каждом хосте (или в CI runner) меняем конфигурацию Docker.
Настройка Docker-клиентов на использование mirror
На Linux-хосте (Docker Engine) создаём или правим /etc/docker/daemon.json:
{
"registry-mirrors": [
"http://vds.example:5000"
]
}
После изменения перезапускаем Docker:
sudo systemctl restart docker
Для CI runner (GitLab Runner, GitHub Actions self-hosted и т.п.) принцип тот же: либо правите daemon.json, либо передаёте mirror через параметры запуска Docker-in-Docker.
Объёмы диска и чистка кеша
Ключевой момент для VDS — диск. Registry как кеш будет расти, пока не закончится место. Минимальные рекомендации:
- выделить под кеш отдельный каталог или раздел;
- периодически чистить старые образы по косвенным признакам (дата изменения каталогов);
- следить за размером каталога (через cron плюс алерты).
Чистка может быть грубой (удалить слои старше N дней). Registry не хранит «последнее использование» в явном виде, но для небольших инсталляций можно периодически удалять старые каталоги blobs и запускать garbage-collect.
apt cache на VDS: ускоряем обновления контейнеров и серверов
Каждый apt update && apt upgrade в Dockerfile или на серверах тянет десятки мегабайт индексов. При CI с десятками параллельных джобов это легально убивает канал. Решение — поднять на VDS HTTP-кеш-прокси для apt.
Вариант: Apt-Cacher-NG как специализированный кеш
Apt-Cacher-NG — простой вариант, который понимает структуру Debian-репозиториев. Устанавливаем на VDS (на примере Debian или Ubuntu):
sudo apt update
sudo apt install apt-cacher-ng
По умолчанию он слушает порт 3142. Дальше два варианта:
- указать его как HTTP-прокси (предпочтительно);
- либо переписать
/etc/apt/sources.listна хостах или в контейнерах.
Использование apt cache через HTTP-прокси
На клиенте (хост или Dockerfile) можно указать прокси так:
echo 'Acquire::http::Proxy "http://vds.example:3142";' | sudo tee /etc/apt/apt.conf.d/01proxy
Для Dockerfile удобнее управлять этим через аргумент сборки:
ARG APT_PROXY
RUN if [ -n "$APT_PROXY" ]; then echo "Acquire::http::Proxy \"$APT_PROXY\";" > /etc/apt/apt.conf.d/01proxy; fi
RUN apt-get update
RUN apt-get install -y curl ca-certificates
RUN rm -rf /var/lib/apt/lists/* /etc/apt/apt.conf.d/01proxy
И при сборке в CI передаёте:
docker build --build-arg APT_PROXY=http://vds.example:3142 -t myimage .
Так вы не жёстко зашиваете URL кеша в образ, а управляете им через аргументы сборки.
Использование Squid в режиме кеша для apt
Если у вас уже есть Squid как общий HTTP-прокси, можно адаптировать его для кеширования apt-репозиториев, настроив ACL под домены Debian и Ubuntu. Это чуть сложнее в настройке, но даёт универсальный HTTP-кеш и для других задач.
Если вы активно используете кеши и для статики, и для API, может быть полезна статья про расширенную работу Nginx с кешем и диапазонными запросами — посмотрите разбор в материале про HTTP Range и кеширование в Nginx и Apache.

npm proxy на VDS: борьба с registry.npmjs.org
Node.js-проекты в CI часто больше всего страдают как раз от npm, yarn или pnpm install: десятки мегабайт пакетов и индексов, иногда скачивающихся по несколько раз за день.
Небольшой npm proxy на VDS решает сразу две проблемы:
- кратное ускорение повторных установок;
- меньше рисков, что очередной лаг внешнего npm-репозитория положит весь пайплайн.
Verdaccio как простой npm proxy
Verdaccio — лёгкое решение для локального npm registry, умеет работать как кеширующий прокси. Базовая установка на VDS:
npm install -g verdaccio
mkdir -p /opt/verdaccio/storage
Шаблонный конфиг config.yaml может выглядеть так:
storage: /opt/verdaccio/storage
listen: 0.0.0.0:4873
uplinks:
npmjs:
url: https://registry.npmjs.org/
packages:
"@*/*":
access: $all
publish: $authenticated
proxy: npmjs
"*":
access: $all
publish: $authenticated
proxy: npmjs
middlewares: {}
logs:
- {type: stdout, format: pretty, level: http}
Запуск:
verdaccio --config /opt/verdaccio/config.yaml
После этого npm, yarn и pnpm можно направить на ваш VDS.
Настройка npm, yarn и pnpm на использование proxy
Для npm достаточно прописать registry:
npm config set registry http://vds.example:4873
Для yarn (classic):
yarn config set registry http://vds.example:4873
Для pnpm:
pnpm config set registry http://vds.example:4873
В CI можно задать это в начале джобы или в файле .npmrc репозитория. Чтобы не ломать локальную разработку, часто разделяют конфиги: локально разработчик использует публичный registry, а CI всегда ходит через VDS.
Общий reverse-proxy и HTTPS для сервисов на VDS
Если на VDS крутится сразу несколько сервисов (Git, registry, Verdaccio, Apt-Cacher-NG), удобно прятать их за одним reverse-proxy, чтобы не думать о портах и сертификатах на каждом сервисе.
Схема именования и маршрутизации
Пример схемы доменных имён (внутри вашей инфраструктуры):
git.internal.example— Git (HTTP или SSH);registry.internal.example— Docker registry mirror;apt.internal.example— HTTP-прокси для apt;npm.internal.example— Verdaccio.
На уровне Nginx вы проксируете соответствующие пути и домены на порты бэкендов. Это даёт:
- единый TLS-терминатор (один набор сертификатов);
- гибкую маршрутизацию и логирование;
- возможность быстро перенастроить backend без изменения URL для клиентов.
Для внешних доменных имён под такой хаб пригодится отдельная регистрация доменов и корректная установка SSL-сертификаты, если часть сервисов должна быть доступна извне.
Интеграция с CI/CD: Git, Docker и кеши
Идеальный сценарий: для пайплайна CI «всё рядом», и Git, и Docker registry, и кеши пакетов — все находятся либо на том же VDS, либо в той же сети дата-центра. Тогда задержки минимальны, а внешний интернет нужен только для первых обращений.
Базовый пайплайн с использованием кешей
Типичный этап пайплайна для Docker-проекта может выглядеть так:
- клонировать код из Git на VDS или его зеркала;
- собрать Docker-образ, используя registry mirror для базовых образов;
- внутри Dockerfile, где нужно, использовать apt cache и npm proxy;
- пушнуть собранный образ в тот же VDS-реестр вместо публичного.
Всё это уменьшает количество взаимодействий с внешними сервисами до минимума.
Типичные проблемы при внедрении и как их обойти
Несколько моментов, с которыми чаще всего сталкиваются админы при развёртывании такого кеш-хаба на VDS:
- DNS и сертификаты. Неочевидные ошибки из-за несоответствия хостнейма и сертификата при переходе на HTTPS. Рекомендуется сразу продумать схему доменных имён и не жонглировать IP в конфигурациях.
- Несколько окружений. Прод, стейдж, тест — все хотят кеш, но не всегда могут делить один и тот же VDS. В простом варианте можно использовать один общий кеш с сегментацией по проектам или namespace в Docker registry и npm.
- Policy безопасности. Иногда политика компании запрещает кешировать внешние артефакты без формальной регистрации. В таком случае заранее согласуйте использование кешей и опишите, что и как там хранится.
Если вы активно работаете с кешированием в Nginx на уровне приложений, будет полезно сравнить подходы с техникой подстановочных субзапросов — об этом есть подробный разбор в статье про Nginx SSI и кеширование сложных страниц.
Ресурсные требования VDS под кеш-хаб
Кеш-хаб не обязан быть монстром по ресурсам, но есть пара тонких моментов.
- CPU. Обычно хватает 2–4 vCPU, если нет экстремальных нагрузок CI.
- RAM. 4–8 ГБ часто достаточно, но если вы крутите там же Git-сервер с UI, Docker registry и npm proxy — лучше смотреть по фактическим метрикам.
- Диск. Главный лимитатор. Docker-образы и npm-пакеты занимают много места, apt — чуть меньше. Лучше взять запас и начать хотя бы со 100–200 ГБ с политикой чистки.
- Сеть. Важнее стабильность и p95–p99 задержки внутри дата-центра, чем номинальные цифры скорости. CI будет бить в ваш VDS очень часто, но малыми порциями.
Такая роль VDS отлично масштабируется по вертикали: по мере роста количества проектов и пакетов можно увеличивать диск и RAM.
Стратегии очистки и управление ростом кешей
Главный страх при внедрении кешей — «оно всё сожрёт диск и умрёт». Это не неизбежно, если изначально продумать политику очистки.
Общие принципы
- мониторинг свободного места и алерты (например, при 80% и 90% заполнения);
- регулярная чистка «древних» артефактов;
- политика «что критично, то не удаляем, остальное — расходный материал».
Для Docker registry чаще всего хватает периодического garbage-collect и очистки неиспользуемых тегов. npm proxy и apt cache обычно поддерживают настройки TTL и лимитов по размеру.
Итоги
Небольшой VDS с правильно настроенными Git, Docker registry mirror, apt cache и npm proxy способен заметно упростить жизнь админам и DevOps:
- ускоряются сборки и деплой;
- снижается зависимость от внешних репозиториев и сетевых лагов;
- появляется единая точка входа для артефактов и зависимостей в вашей инфраструктуре.
Эту схему можно внедрять поэтапно: начать с Docker registry mirror и apt cache, затем добавить npm proxy и при необходимости Git-сервер или зеркало. Так вы быстро снимаете самые болезненные точки и постепенно обрастаете удобной инфраструктурой вокруг CI/CD.


