Архитектура
Компоненты, обработка запросов и сбоев, границы безопасности.
Компоненты
cmd/oci-mirror-proxy точка входа; вызывает internal/cli
internal/cli команды, разбор параметров, форматирование вывода
internal/app корень композиции: состояние конфигурации, пулы, таблица маршрутов
internal/frontend HTTP-интерфейс Registry v2 для dockerd
internal/route диспетчер, цепочки middleware, атомарная замена таблицы маршрутов
internal/middleware журналирование, возобновление загрузки blob
internal/scheduler последовательная стратегия и гонка запросов; контракт Candidate
internal/upstream источник (endpoint), его circuit breaker и транспорт; пул с обновлением по конфигурации
internal/auth авторизация для каждого источника: none, basic, token
internal/secret ссылки на секреты и скрытие значений
internal/config модель конфигурации, значения по умолчанию, проверка, файловый ввод-вывод
internal/ociapi разбор путей реестра; конечный пакет без внутренних зависимостей
internal/admin API управления через Unix-сокет и его клиент
internal/daemonconf формирование конфигурации dockerd, резервные копии, атомарное обновление каждого файла
internal/unixhttp HTTP через Unix-сокеты для admin и daemonconf
internal/fsutil атомарная запись файлов
internal/cache резервная точка расширения для кеша blob (только интерфейс)Обработка запроса
- dockerd отправляет
GET /v2/library/nginx/manifests/latest. frontendразбирает путь черезociapi, определяя псевдоним (docker.io), тип (манифест), репозиторий и ссылку. Пути вне грамматики реестра возвращают 404. Принимаются только GET и HEAD.frontendвыбирает маршрут для псевдонима реестра.- Выполняется цепочка диспетчера: журналирование, возобновление blob, затем маршрут.
- Маршрут получает снимок включённых источников из пула и вызывает стратегию.
- Стратегия пробует источники. Каждая попытка проходит через
Endpoint.Attempt: проверяет circuit breaker, отправляет запрос, применяет тайм-ауты первого байта и общий тайм-аут, при необходимости обрабатывает один запрос аутентификации и записывает результат. - Возвращается первый приемлемый ответ (2xx). Разрешённые заголовки копируются по белому списку; тело передаётся потоком.
Обработка сбоев
| Событие | Действие |
|---|---|
| Отказ соединения или неотвечающий источник | Считается сбоем; проверяется другой источник. timeouts.connect отдельно ограничивает установку TCP-соединения и TLS-рукопожатие; timeouts.first_byte — ожидание заголовков ответа. |
| 5xx или 429 | Считается сбоем. |
| 401 с запросом Bearer-аутентификации | Обрабатывается один раз: получается токен и повторяется запрос. Второй 401 исключает кандидата из выбора, но не считается сбоем доступности для circuit breaker. |
| 404 | Не считается проблемой доступности. Проверяется следующий источник. Если все опробованные источники вернули 404, прокси возвращает 404, и dockerd использует резервный путь. |
| Circuit breaker разомкнут | Попытка пропускается без сетевого запроса. |
| Обрыв передачи blob | Загрузка продолжается с текущего смещения на другом источнике, если тот возвращает 206 с Content-Range, начинающимся с того же смещения. Иначе возвращается исходная ошибка. Не более трёх возобновлений на загрузку. |
| Отключение клиента | Контекст запроса отменяется, стратегия останавливается, дальнейшая запись прекращается. |
| Все источники завершились с ошибкой, не 404 | 502 UNAVAILABLE. dockerd использует резервный путь. |
Стратегии
Последовательная (race.enabled: false): по одному источнику в настроенном порядке. Следующий вызывается только после сбоя предыдущего.
Гонка запросов с задержкой (hedged, включена по умолчанию): первый источник запускается сразу. Если за race.delay нет ответа, запускается следующий, до race.max_parallel одновременных попыток. При сбое попытки следующий источник запускается немедленно. Первый приемлемый ответ побеждает; остальные попытки отменяются.
Перечитывание конфигурации
Изменения источников вступают в силу без перезапуска прокси. Неизменённые источники сохраняют состояние circuit breaker и счётчики. Некорректная конфигурация отклоняется; прежняя продолжает обслуживать запросы.
Перечитывание не прерывает текущие HTTP-передачи и не меняет кандидатов для их возобновления. Последующие HTTP-запросы, в том числе в рамках того же docker pull, используют новую конфигурацию. См. изменение конфигурации.
Границы безопасности
- Интерфейс передачи данных не использует аутентификацию и по умолчанию слушает loopback.
- API управления доступен только через сокет, защищённый правами файловой системы.
- Учётные данные ограничены своим источником.
Authorizationклиента удаляется на входе. Политика перенаправлений Gonet/httpудаляетAuthorizationпри переходе на посторонний домен, но может сохранять его для исходного домена и его поддоменов. Настраивайте только доверенные источники и адреса аутентификации (realm). - Целостность содержимого проверяется сквозным образом: dockerd проверяет каждый дайджест. Неисправный источник может сорвать загрузку, но не может заставить принять образ с неверным содержимым.