Перейти к основному содержимому

Огранчиение доступа к сервисам в Docker

Здесь и далее IPv4-адрес сервера 192.0.2.10.

Отключение внешнего доступа

При запуске с помощью "docker run"

Если доступ к сервису нужен только приложениям, работающим на этом же сервере, то пробрасывать порты становится необязательно. Рассмотрим этот момент подробнее.

Типичная команда для запуска сервиса в docker выглядит так:

$ docker run --name my-memcache -p 11211:11211 -d memcached

Здесь опция для проброса портов - -p или --publish. В данном виде она подключает порт 11211 с контейнера на такой же порт на основном сервере, и можно подключаться к нему по адресам вида 127.0.0.1:11211 и 192.0.2.10:11211.

Чтобы запустить сервис только на локальном IP, достаточно изменить команду запуска так:

docker run --name my-memcache -p 127.0.0.1:11211:11211 -d memcached

Либо, можно вообще не пробрасывать порт (исключить из команды -p 11211:11211) и подключаться к сервису, используя IP-адрес контейнера, узнать который можно из вывода docker inspect CONTAINER_NAME.

При запуске с помощью "docker compose"

Приведем часть compose-файла, обычно отвечающего за запуск контейнеар на нужном порту:

services:
app:
image: memcached
ports:
- 11211:11211

Здесь также, чтобы монтировать порты только на 127.0.0.1, указываем его:

services:
app:
image: memcached
ports:
- 127.0.0.1:11211:11211

Либо убираем подключение полностью, чтобы работать через IP контейнера:

services:
app:
image: memcached

Огранчиение доступа к контейнеру

Если внешний доступ к контейнеру все же нужен для других серверов, то можно ограничить доступ к нему с помощью правил iptables.

Чтобы обеспечивать проброс портов и прочую маршрутизацию, Docker задействует несоклько своих цепочек правил, подразумевая, что свои правила мы добавляем в цепочку DOCKER-USER:

iptables -I DOCKER-USER  ! -i lo -p tcp -m tcp --dport 11211 -j DROP
iptables -I DOCKER-USER ! -i lo -p udp -m udp --dport 11211 -j DROP
iptables -I DOCKER-USER -p tcp -m tcp -s 198.51.100.11 --dport 11211 -j ACCEPT
iptables -I DOCKER-USER -p udp -m udp -s 198.51.100.11 --dport 11211 -j ACCEPT

Здесь IP 198.51.100.11 - адрес сервера, которому подключения разрешены. Если нужно разрешить несколько IP, просто повторите последние два правила с нужными адресами.

Поскольку при перезапуске сервера правила в файерволе не сохраняются, то потреубется реализовать метод, которым они будут восстановлены. Вариантом решения является добавление правил при старте сервиса docker.service в системе. Сделать это можно следующим образом:

  1. Модифицируем сервис systemd, добавляя запуск скрипта после старта сервиса и после остановки:

    mkdir -p /etc/systemd/system/docker.service.d
    echo -e '[Service]\nExecStartPost=/etc/iptables_docker_start.sh\ExecStopPost=/etc/iptables_docker_stop.sh' \
    > /etc/systemd/system/docker.service.d/iptables.conf
    systemctl daemon-reload
  2. Создаем файлы скриптов:

    echo '#!/bin/bash' > /etc/iptables_docker_start.sh
    echo '#!/bin/bash' > /etc/iptables_docker_stop.sh
    chmod u+x /etc/iptables_docker_start.sh /etc/iptables_docker_stop.sh
  3. Вносим в скрипт /etc/iptables_docker_start.sh команды, необхоимые для огранчиения доступа, после строки #!/bin/bash.

  4. Вносим в скрипт /etc/iptables_docker_stop.sh команды, удаляющие внесенные правила, после строки #!/bin/bash - просто замените флаг -I на -D. Это нужно, чтобы при перезапуске docker правила не дублировались.