Статьи

Разверните и настройте локальный прокси-сервер кэширования Docker.

Недавно я искал кеширование загрузки слоев Docker для среды разработки Fabric8 , чтобы позволить мне уничтожать виртуальные машины, на которых работал мой демон Docker, и все еще избегать повторной загрузки базовых образов каждый раз, когда я воссоздаю свой виртуальный компьютер.

Как обычно, я сначала попытался поразить Google, и мне было указано на пару страниц:

и

Поскольку я довольно часто использую подход Джерома Петаццони для прозрачного Squid + iptables для кеширования и перехвата простого http-трафика (обычно HTTP-вызова из Java-программ), я обнаружил, что первое основанное на решении решение имело смысл, поэтому я попробовал его в первую очередь.

Оказалось, что я искал вторую ссылку ; но я все еще провел несколько хороших часов обучения с неработающими предложениями из первого, изучая трудный путь, которым Squid не играет так хорошо с Amazon Cloudfront CDN, используемой Docker Hub. Но я должен признать, что это было весело .
Теперь я знаю, как перенаправлять вызовы в Squid для попадания на промежуточные перехватчики, которые искажают параметры запросов, заголовки и все остальное.
Я не смог найти рабочую комбинацию для Cloudfront, но теперь я, вероятно, могу воспроизвести печально известную розыгрыш Cats Proxy Prank . знак равно

В любом случае, как я уже говорил, я действительно искал вторую ссылку, которая показывает вам, как настроить промежуточный прокси-сервер Docker, на которую ваш Docker-демон будет пытаться подключиться, перед тем как по умолчанию использовать обычные общедоступные серверы Docker Hub.

Почти все, что мне было нужно, было на этой странице, но я обнаружил, что информация была немного более загадочной, чем нужно . Основная причина этого в том, что в этом примере предполагается, что мне нужна безопасность (TLS), что на самом деле не мой случай, поскольку прокси полностью локальный. Кроме того, он показывает, как настроить реестр Docker с использованием конфигурации YAML . Опять же, не очень сложно, но на самом деле больше, чем нужно. Да, потому что то, что вам действительно нужно для вызова простейшего локального (не защищенного) прокси-сервера Docker, — это oneliner :

1
2
3
docker run -p 5000:5000 -d --restart=always --name registry   \
  -e REGISTRY_PROXY_REMOTEURL=http://registry-1.docker.io \
  registry:2

Интересно, что образ registry поддерживает альтернативный способ пересылки конфигурации , что избавляет вас от передачи файла конфигурации YAML. Идея, описанная здесь , заключается в том, что если вы следуете соглашению об именовании переменных среды , которое отражает иерархию дерева YAML, вы можете превратить что-то вроде:

1
2
3
4
...
proxy:
  remoteurl: http://registry-1.docker.io
...

Это вы должны записать в файл .yaml и перейти к процессу следующим образом:

1
2
3
docker run -d -p 5000:5000 --restart=always --name registry \
  -v `pwd`/config.yml:/etc/docker/registry/config.yml \
  registry:2

В гораздо более -e REGISTRY_PROXY_REMOTEURL=http://registry-1.docker.io переменная среды выполнения! Давайте немного улучшим пример, чтобы мы также передавали нашему прокси-серверу Docker энергонезависимое хранилище для кэшированных слоев, чтобы мы не теряли их между вызовами:

1
2
3
4
docker run -p 5000:5000 -d --restart=always --name registry   \
  -e REGISTRY_PROXY_REMOTEURL=http://registry-1.docker.io \
  -v /opt/shared/docker_registry_cache:/var/lib/registry \
  registry:2

Теперь у нас есть все, что нужно для сохранения значительной доли пропускной способности, каждый раз, когда нам нужно получить изображение Docker, которое уже прошло через наш локальный прокси. Осталось только сказать нашему демону Docker, что он знает о новом прокси :

1
2
3
# update your docker daemon config, according to your distro
# content of my `/etc/sysconfig/docker` in Fedora 23
OPTIONS=" --registry-mirror=http://localhost:5000"

Перезагрузите (или перезапустите) ваш демон Docker, и все готово! Просто имейте в виду, что если вы перезапустите демон, вам также может понадобиться перезапустить контейнер Registry, если вы работаете на одном узле.

Интересно, что стало известно, что демон Docker не ломается, если не может найти указанное registry-mirror . Таким образом, вы можете добавить конфигурацию и забыть о ней, зная, что ваше взаимодействие с Docker Hub принесет только пользу от возможных попаданий в ваш кеширующий прокси, при условии, что он работает.

Вы можете видеть, как это работает со следующими тестами:

1
docker logs -f registry

будет регистрировать все исходящие запросы на загрузку , и как только набор запросов, составляющих одну операцию pull image будет завершен, вы также сможете проверить, что изображение теперь полностью обслуживается вашим прокси-сервером с помощью этого вызова:

1
2
3
curl http://localhost:5000/v2/_catalog
# sample output
{"repositories":["drifting/true"]}

Эта статья была бы закончена, но, поскольку мне плохо показывать, как отключить безопасность в Интернете , вот также очень короткий и полностью работающий и протестированный пример того, как реализовать то же самое с включенным TLS :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
# generate a self signed certificate; accept default for every value a part from Common Name where you have to put your box hostname
mkdir -p certs && openssl req  -newkey rsa:4096 -nodes -sha256 -keyout certs/domain.key  -x509 -days 365 -out certs/domain.crt
 
# copy to the locally trusted ones, steps for Fedora/Centos/RHEL
sudo cp certs/domain.crt /etc/pki/ca-trust/source/anchors/
 
# load the newly added certificate
sudo update-ca-trust enable
 
# run the registy using those keys that you have generated, mounting the files inside the container
docker run -p 5000:5000 --restart=always --name registry \
  -v `pwd`/certs:/certs \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  -e REGISTRY_PROXY_REMOTEURL=https://registry-1.docker.io \
  registry:2
 
# now you just need to remember that you are working in https, so you need to use that protocol in your docker daemon configuration, instead of plain http; also use that when you interact with the API in curl