Как мы docker с VPN дружили
В прошлом году столкнулся с задачей по настройке VPN-подключения внутри docker для обеспечения доступа к API, находящемуся во внутренней сети предприятия. Недавно с подобной проблемой столкнулся и мой друг, но ситуации у нас несколько разные: я настраивал связку для openfortivpn
, а ему нужно было настроить для openvpn
.
Основная проблема, которая возникает при настройке vpn-соединения для нескольких контейнеров заключается в необходимости настройки сетевых параметров и особенностях работы docker. Без контейнеризации всё было бы намного проще: вы запускаете VPN-подключение и все ваши запросы к соответствующим хостам внутри vpn-сети проходят через это подключение.
Как работает сеть в docker и docker-compose
По умолчанию, все наши сервисы объединяются в рамках сети default. При необходимости мы можем выделять отдельные сети для разных сервисов, чтобы изолировать их друг от друга. Кроме прочего, мы можем использовать внешнюю docker-сеть, чтобы объединить сервисы из разных приложений (отделённых своими compose-файлами) между собой.
Нетрудно догадаться, что для обеспечения vpn-подключения внутри docker-сети, нам потребуется уметь чуть больше, чем просто создание docker-сети. Тут на помощь приходят сетевые драйверы и network_mode.
Сетевые драйверы
В официальной документации описано целых 7 различных сетевых драйверов. Начнём с того, что сам по себе сетевой драйвер нужен для расширения возможностей сети. Рассмотрим какие сетевые драйверы существуют (адаптированная информация из документации):
- bridge — драйвер по умолчанию, необходим для того, чтобы сервисы могли общаться друг с другом внутри docker-сети;
- host — драйвер, который позволяет использовать сеть хоста напрямую, убирая изоляцию контейнера от хоста;
- overlay — драйвер, позволяющий соединить несколько хостов, где находятся docker-контейнеры вместе, чтобы обеспечить взаимодействие между ними (такой вариант отлично подходит для обеспечения коммуникации между нодами в swarm mode);
- ipvlan — драйвер, предоставляющий полный контроль над адресацией IPv4 и IPv6;
- macvlan — драйвер, позволяющий назначить MAC-адрес для контейнера, делая его доступным в виде физического устройства внутри вашей сети;
- none — драйвер, позволяющий изолировать сеть контейнера от хостовой сети и сети других контейнеров;
- network plugins — возможность использования в качестве сетевого драйвера любого внешнего решения.
network_mode
network_mode
это атрибут сервиса внутри конфигурации docker-compose, необходимый для более тонкой настройки. Существует несколько значений у атрибута newtork_mode
:
bridge
— дефолтный способ для связи между контейнерами, работает по умолчанию;host
— использование единого сетевого пространства между выбранным сервисом и хостом;none
— отсутствие сетевого взаимодействия для выбранного сервиса;service:[service_name]
— использование сетевого пространства выбранного сервиса;container:[container_name/id]
— использование сетевого пространства выбранного контейнера (отличается от прошлого необходимость указания именно container_name/container_id, а не service_name).
К сожалению, в официальной документации compose, подробно ничего не сказано об этом атрибуте, кроме ссылки на то, что значения могут быть те же самые, что и у парамерта --network
, но также добавляется специальная форма service:[service name]
. Возможно, это сделано так именно потому, что все значения по смыслу похожи.
Пример compose-файла
Разницы для конфигурации между openfortivpn
и openvpn
особо нет, поэтому рассмотрим на примере openfortivpn
:
services: vpn: container_name: openfortivpn restart: unless-stopped build: . privileged: true volumes: - ./config:/etc/openfortivpn/config.conf command: ["openfortivpn", "--config=/etc/openfortivpn/config.conf"] some-service: image: your-container-image network_mode: service:vpn