Як налаштувати параметри проксі в контейнерах Docker
Docker і проксі-си стикаються в найнесподіваніших місцях. Збірка працює на одному ноутбуці, а потім падає на CI-ранері, і найчастіше бракує всього лише однієї змінної проксі.
У цьому посібнику показано, як налаштувати проксі в контейнерах Docker для одного docker run, для збірки образів і для повторного використання на всьому хості. Точний спосіб залежить від області застосування, а не від здогадок, коли потрібно налаштувати проксі в Docker контейнері.
Одразу попередимо: параметри проксі всередині контейнерів — не магія. Вони допоможуть лише тоді, коли контейнер справді може дістатися до хоста проксі, а проксі дозволяє потрібний вам напрямок.
1. Перевірте контекст контейнера та область дії проксі
Почніть із відповіді на одне питання: проксі потрібен для одного запущеного контейнера, для docker build чи для кожного контейнера, який запускає розробник або CI-завдання? Від цього залежить, куди саме має потрапити налаштування.
Один docker run — найпростіший варіант. Ви один раз передаєте змінні середовища, контейнер їх використовує, а після видалення контейнера зміна зникає.
Проксі на етапі збірки — це інше. Менеджери пакетів усередині образу, такі як apt, apk, pip або npm, можуть потребувати проксі під час створення шарів, навіть якщо фінальному контейнеру він не потрібен.
Глобальні налаштування на рівні хоста найменш помітні. Вони економлять час на введення, але водночас приховують той факт, що контейнер успадковує поведінку проксі з конфігурації Docker-клієнта, а не з самого образу.
Якщо ви обираєте між мережевими шляхами для автоматизації, наш посібник як обрати VPN допоможе зрозуміти, чому одному середовищу може знадобитися інший вихідний маршрут, ніж іншому.
2. Визначте значення проксі, які потрібні Docker
Перед тим як писати команду, вам потрібні точна URL-адреса проксі, порт і будь-які облікові дані. Попросіть мережеву команду надати повну форму, а не лише назву хоста, записану в чаті.
Значення проксі часто виглядає як http://proxy.example.com:3128 або https://proxy.example.com:8443. Якщо потрібна автентифікація, вкажіть користувача й пароль у форматі, який визначила ваша команда.
Запишіть внутрішні адреси, які мають обходити проксі. До цього списку можуть входити імена сервісів, приватні домени, хости баз даних або суфікси кластера.
Одна деталь часто губиться: один і той самий проксі може добре обробляти вебтрафік, але не справлятися з незвичними портами. Якщо контейнеру потрібні лише завантаження пакетів, це менш важливо, ніж коли він ще й спілкується з внутрішніми API.
Перш ніж показувати облікові дані в журналах або історії оболонки, перегляньте посібник із найкращих практик автентифікації проксі. Пароль у командному рядку живе недовго, а пам’ятається довго.
3. Передайте змінні проксі в запущений контейнер
Для одного сеансу контейнера використовуйте docker run зі змінними середовища. Docker і більшість поширених інструментів усередині контейнера розпізнають HTTP_PROXY, HTTPS_PROXY і NO_PROXY, а також їхні варіанти в нижньому регістрі в багатьох образах; це і є docker run proxy змінні середовища в практичному застосуванні.
Простий приклад виглядає так:
docker run -e HTTP_PROXY=http://proxy.example.com:3128 -e HTTPS_PROXY=http://proxy.example.com:3128 myimage- Додайте
-e NO_PROXY=localhost,127.0.0.1,.internal.example.com, якщо внутрішні служби мають залишатися прямими. - Повторіть із назвами в нижньому регістрі, якщо цього очікують інструменти образу.
Деякі базові образи читають лише назви у верхньому регістрі. Деякі інструменти підтримують обидва варіанти. Це незручно, але так є насправді, тож перевіряйте на точному образі, який ви постачаєте.
Ви також можете покласти змінні у файл Compose або у файл середовища й дати Docker прочитати їх звідти, але принцип не змінюється: контейнер має отримати значення проксі під час запуску.
Одна дрібниця має значення. Якщо контейнер стартував без змінної, застосунок усередині нього вже не здогадається про проксі пізніше.
4. Налаштуйте проксі для збірки образів
Параметри проксі на етапі збірки важливі тоді, коли Dockerfile встановлює пакети або завантажує вихідний код із мережі. Образ може зібратися без проблем в одній мережі й зламатися в іншій, бо етап збірки не може дістатися зовнішніх репозиторіїв.
Використовуйте docker build із проксі, переданими як аргументи збірки або значення середовища, залежно від інструментів і версії Docker. Мета — зробити проксі видимим під час збірки, а не лише під час виконання; саме для цього підходить docker build проксі build-arg.
Поширений підхід — передавати аргументи так:
docker build --build-arg HTTP_PROXY=http://proxy.example.com:3128 --build-arg HTTPS_PROXY=http://proxy.example.com:3128 -t myimage .- Додайте ті самі значення в
NO_PROXY, якщо етапи збірки мають напряму звертатися до внутрішніх дзеркал. - Не залишайте значення проксі у фінальному середовищі виконання, якщо це справді не потрібно застосунку.
Багатоступеневі збірки потребують особливої уваги. Перший етап може потребувати зовнішнього доступу для встановлення залежностей, тоді як фінальному етапу може не знадобитися жодна змінна проксі. Якщо про це забути, фінальний образ може тягнути за собою налаштування, які ніколи не використовує.
Під час збірки Docker також може завантажувати базові образи через демон Docker, а це окремо від процесу всередині контейнера. Тобто одне налаштування проксі може допомогти кроку в Dockerfile, а інше потрібно на хості Docker, якщо завантаження образів не вдається ще до початку збірки.
Для ширшого погляду на поведінку проксі в скрейпінгу та автоматизації перегляньте посібник із ротації проксі для вебскрейпінгу. Механіка інша, але потреба керувати напрямками та режимами відмови дуже схожа.
5. Зробіть налаштування проксі постійними через конфігурацію Docker-клієнта
Постійно повторювати одні й ті самі прапорці швидко набридає. Якщо ви щодня працюєте з одним і тим самим проксі, конфігурація Docker-клієнта може зберігати типові значення, щоб нові контейнери успадковували їх без повторного введення.
Зазвичай це зручність на боці клієнта, а не хитрість у Dockerfile. Це допомагає розробникам і CI-ранерам запускати контейнери з тими самими значеннями проксі, але не переписує образ.
Використовуйте цей шлях, якщо ваша команда очікує стабільний проксі для більшості завдань. Не використовуйте його, якщо проксі потрібен лише одному проєкту, бо тоді кожен новий контейнер на цій машині успадковуватиме налаштування, які йому можуть не знадобитися.
Одним із практичних наслідків є передбачуваність. Розробник запускає тестовий контейнер о 9:00, а він уже знає, куди має йти вихідний трафік.
Якщо перед роботою з файлами конфігурації вам потрібне коротке ознайомлення з термінами, глосарій VPN і проксі пояснює поняття без зайвої теорії.
6. Обробіть винятки no-proxy для внутрішніх сервісів
NO_PROXY — це місце, де багато конфігурацій Docker дають збій. Якщо список надто широкий, інтернет-запити оминатимуть проксі тоді, коли цього не слід робити. Якщо він надто вузький, звернення до внутрішніх сервісів можуть піти через проксі, який не здатен до них дістатися.
Складіть список на основі реальних адрес. Додайте localhost, 127.0.0.1, імена сервісів, які використовує Compose, суфікси приватних доменів і кінцеві точки кластера, що живуть усередині вашої мережі.
Не припускайте, що крапки однаково працюють у всіх інструментах. Деякі парсери сприймають .example.com як збіг для всіх піддоменів, тоді як інші краще обробляють example.com. Перевіряйте точну форму, яку використовує ваш образ.
Для імен у стилі Kubernetes контейнеру може знадобитися обійти проксі для service.namespace.svc.cluster.local або для ширшого суфікса кластера. Один такий рядок може запобігти тижню незрозумілих тайм-аутів.
Гарна звичка — записувати список обходу поруч зі значенням проксі в тому самому місці. Розділена конфігурація провокує помилки.
7. Перевірте поведінку всередині контейнера
Ніколи не довіряйте прапорцю, доки не перевірите контейнер зсередини. Спочатку відкрийте оболонку в контейнері й виведіть змінні середовища, а потім протестуйте запит до зовнішнього й внутрішнього хоста.
Наприклад, запустіть env | grep -i proxy всередині контейнера й переконайтеся, що значення присутні. Потім використайте curl або сам менеджер пакетів, щоб зробити один вихідний запит.
Якщо проксі працює, запит має або пройти через проксі успішно, або завершитися помилкою, пов’язаною саме з проксі. Якщо ж він випадково обходить проксі, той самий запит може з’єднатися напряму й приховати помилку до пізніше.
Перевірте щонайменше дві цілі: один публічний сайт і один внутрішній сервіс. Різниця покаже, чи обидва шляхи — через проксі та в обхід — працюють так, як очікується.
Якщо вам потрібен ще один спосіб перевірити зовнішній маршрут, наша стаття як перевірити, чи приховано вашу IP-адресу пропонує корисний підхід: спочатку перевірте видиму точку виходу, а вже потім припускайте, що все налаштовано правильно.
8. Налаштуйте проксі для поширених робочих сценаріїв Docker
Compose, багатоступеневі збірки та CI-завдання додають ще один шар. Одного прапорця docker run може бути досить на ноутбуці, але конвеєру, який збирає, тестує й постачає образ, часто потрібен проксі в кількох місцях.
Docker Compose може передавати значення середовища в сервіси, але секції збірки все одно можуть потребувати окремих аргументів для build. Це означає, що одне й те саме значення проксі може з’являтися один раз для часу збірки і ще раз для часу виконання.
CI-завдання часто зберігають значення проксі в маскованих змінних або секретах конвеєра. Потім завдання підставляє їх у кроки docker build і docker run, щоб контейнер міг діставатися до дзеркал пакетів і зовнішніх API в межах одного й того самого процесу.
Багатоступеневі збірки заслуговують ще однієї перевірки. Якщо ранній етап використовує проксі, а пізніший копіює лише бінарні файли, фінальному етапу може взагалі не знадобитися жодна змінна проксі. Якщо прибрати її звідти, буде менше зайвого й менше плутанини потім.
Системи оркестрації контейнерів теж можуть додавати власні правила. Опис сервісу, sidecar і агент збірки можуть використовувати різні шляхи, тому не слід вважати, що одна й та сама URL-адреса проксі працюватиме всюди без перевірки.
Для трафіку, подібного до браузерного, або роботи з кількома протоколами важливо не лише те, чи є проксі, а й який саме тип підходить для завдання. Порівняння в SOCKS5-проксі проти HTTP-проксі корисне, коли контейнер має спілкуватися з кількома типами кінцевих точок.
Практичні шаблони команд
Ці шаблони охоплюють найпоширеніші випадки. Назви можуть відрізнятися залежно від образу, але логіка — ні.
| Випадок | Що задати | Куди це додати |
|---|---|---|
| Один контейнер | HTTP_PROXY, HTTPS_PROXY, NO_PROXY |
docker run -e ... |
| Збірка образу | Аргументи збірки для значень проксі | docker build --build-arg ... |
| Повторне локальне використання | Типові параметри проксі | Конфігурація Docker-клієнта |
| Внутрішні сервіси | Список NO_PROXY з хостами та суфіксами |
Те саме місце, що й значення проксі |
| CI-конвеєр | Масковані змінні проксі | Секрети конвеєра або середовище завдання |
Для проксі з автентифікацією, якщо можливо, тримайте обробку облікових даних окремо від образу. Так зменшується ризик залишити секрет у шарі, у файлі журналу чи в копії історії оболонки.
Останній пункт заслуговує на чітке число: тестуйте і шлях через проксі, і шлях в обхід нього перед тим, як зливати зміни. Дві перевірки краще за одну, а одна краща за жодної, але саме дві допоможуть зловити очевидні помилки, через які контейнер виглядає справним, хоча тихо спрямовує трафік не туди.