Опубликовано 9 октября 2026 г. · Обновлено 9 октября 2026 г.
Безопасность Docker-хоста на VPS: опубликованные порты, сокет Docker и rootless-режим
Docker упрощает развёртывание, и за этой простотой прячутся три факта, на которых попадаются владельцы небольших серверов. Опубликованный порт открыт в интернет, даже если файрвол утверждает обратное. Всё, что может обращаться к демону Docker, фактически является root на хосте. А контейнер не граница безопасности, на которую можно полагаться без дополнительных настроек. Это руководство о стороне хоста: как Docker взаимодействует с файрволом, кто может управлять демоном и каких флагов контейнеров стоит избегать. Оно намеренно про конфигурацию, а не про отдельную атаку; свежий реальный пример использования Docker-хостов атакующими после уязвимости в приложении смотрите в статье о приоритетах патчинга по каталогу KEV. Для общей базы начните с чек-листа безопасности VPS.
В этой статье
Опубликованные порты обходят файрвол Привязка к localhost и прокси впереди Фильтрация цепочкой DOCKER-USER Сокет Docker это root Не открывайте API демона без TLS Важные флаги контейнеров Rootless-режим и обновления Часто задаваемые вопросыБыстрый результат (10 минут)
- Выполните
docker ps --format "table {{.Names}}\t{{.Ports}}"и поищите0.0.0.0или[::]в столбце портов. - Для каждого сервиса, который нужен только вашему обратному прокси или другим контейнерам, замените проброс на
127.0.0.1:ХОСТ:КОНТЕЙНЕР. - Выполните
ss -tlnp | grep -E "2375|2376". На портах API Docker не должно быть слушающих процессов. - Найдите в compose-файлах
/var/run/docker.sockиprivileged: trueи отметьте каждое совпадение. - Выполните
getent group dockerи убедитесь, что в группе только те, кому вы доверили бы root.
Опубликованные порты обходят файрвол
Многие настраивают ufw, разрешают только SSH и HTTPS и считают дело сделанным. Затем запускают контейнер с -p 8080:80, и порт доступен отовсюду. Документация Docker объясняет причину: Docker маршрутизирует трафик контейнеров в таблице nat, поэтому пакеты перенаправляются до того, как попадут под правила файрвола, которыми управляет ufw, и, по формулировке документации, пакеты маршрутизируются до применения правил файрвола, что фактически игнорирует вашу конфигурацию.
Docker также прямо пишет, что публикация портов контейнеров небезопасна по умолчанию, и что без указания конкретного адреса хоста демон публикует порты на всех адресах хоста (0.0.0.0 и [::]). На практике это значит: база данных, админ-панель или очередь сообщений, опубликованные для удобства, открыты в интернет, пока ufw status не показывает ничего плохого. Docker советует и не изменять создаваемые им правила, поэтому описанные ниже способы обходят их, а не правят.
Привязка к localhost и прокси впереди
Простейшее решение: публиковать только на адрес loopback. Документация Docker приводит такую форму для ограничения порта самим хостом:
docker run -p 127.0.0.1:8080:80 -p '[::1]:8080:80' nginx
В compose-файле это "127.0.0.1:8080:80" в разделе ports. Затем поставьте на хост обратный прокси, например nginx, слушающий 80 и 443 и перенаправляющий на эти локальные порты, чтобы публичными входами были только те, что вы настроили осознанно и можете защитить разумными настройками nginx. Сервисы, которые общаются только друг с другом, вообще не публикуйте, а поместите в пользовательскую сеть Docker. Важнее всего это для баз данных: см. как найти и закрыть открытые базы данных.
Фильтрация цепочкой DOCKER-USER
Когда порт действительно должен быть публичным, но только для определённых адресов, фильтруйте в цепочке, которую Docker предусмотрел для этого. Документация описывает DOCKER-USER как место для пользовательских правил, которые обрабатываются до правил в цепочках DOCKER-FORWARD и DOCKER. Её пример отбрасывает трафик со всех адресов, кроме одного:
iptables -I DOCKER-USER -i eth0 ! -s 203.0.113.10 -j DROP
Две детали с той же страницы сэкономят часы отладки. Во-первых, документация предупреждает, что может понадобиться разрешить ответы от серверов вне разрешённых диапазонов командой iptables -I DOCKER-USER -m state --state RELATED,ESTABLISHED -j ACCEPT, поставленной перед правилами drop. Во-вторых, в этой цепочке адрес назначения пакетов уже переписан, поэтому для сопоставления исходного адреса и порта нужно расширение conntrack, которое, по словам документации, может снижать производительность. Замените eth0 на ваш публичный интерфейс, проверьте со второго подключения и держите сессию SSH открытой. Добавленные так правила не переживают перезагрузку, пока вы не сохраните их средствами вашего дистрибутива.
Сокет Docker это root
Демон слушает Unix-сокет /var/run/docker.sock. Кто может писать в него, тот управляет демоном, а демон работает от root. Документация по безопасности Docker показывает, насколько это серьёзно: можно запустить контейнер, в котором корень хоста / смонтирован внутрь, после чего контейнер может без ограничений изменять файловую систему хоста. Там же сказано, что управлять демоном Docker должны только доверенные пользователи.
Отсюда два вывода. Членство в группе docker это root: в собственных заметках Docker после установки сказано, что группа даёт пользователю привилегии уровня root, поэтому относитесь к ней как к sudo и оставляйте только тем, кому доверили бы root (см. пользователи, sudo и минимальные привилегии). А монтирование сокета в контейнер, которого просят многие системы мониторинга и CI-раннеры, отдаёт этому контейнеру хост. Памятка OWASP по безопасности Docker категорична: доступ к сокету равнозначен неограниченному root-доступу к хосту, а монтирование только для чтения не делает API Docker доступным только для чтения. Если инструмент настаивает на сокете, запускайте его, только если доверяете ему как root, либо используйте прокси сокета, открывающий лишь нужные вызовы API. Краткая версия есть в статье глоссария.
Не уверены, какие порты действительно публичны?
Бесплатная проверка в режиме только чтения показывает сервисы, доступные из интернета, включая опубликованные Docker, ничего не меняя.
Получить бесплатную проверку сервера Связаться с инженером по безопасностиНе открывайте API демона без TLS
Демон может слушать и TCP, чтобы им можно было управлять удалённо. Документация называет порты по умолчанию: 2376 при использовании TLS и 2375 в остальных случаях, предупреждает, что такой доступ может сделать вас уязвимым к несанкционированному доступу к хосту и другим атакам, а удалённые непривилегированные пользователи могут получить root на хосте. Там же сказано, что удалённый доступ без TLS не рекомендуется и в будущем потребует явного согласия. Руководство по безопасности идёт дальше: защита конечных точек API через HTTPS и сертификаты обязательна.
Для одного VPS это почти никогда не нужно. Если вы хотите запускать команды Docker с ноутбука, создайте контекст через SSH (docker context create vps --docker "host=ssh://user@your-server"): он использует вашу защищённую настройку SSH и ключевую аутентификацию вместо новой двери. Командой из быстрого результата убедитесь, что на 2375 и 2376 никто не слушает.
Важные флаги контейнеров
Памятка OWASP даёт короткий список, закрывающий большую часть риска:
- Не запускайте с
--privileged. В справочнике Docker сказано, что флаг даёт контейнеру все capabilities и открывает доступ ко всем устройствам хоста. Он снимает большую часть изоляции, на которую вы рассчитывали. - Задайте не-root пользователя. OWASP называет непривилегированного пользователя лучшим способом предотвратить атаки повышения привилегий. Используйте
USERв образе илиuser:в compose. - Сбрасывайте capabilities. Самая безопасная настройка: сбросить все capabilities через
--cap-drop allи добавить только необходимые. - Блокируйте получение привилегий. Запускайте контейнеры с
--security-opt=no-new-privileges. - Обновляйте хост. Первое правило OWASP: контейнеры используют ядро хоста, поэтому уязвимое ядро означает уязвимый контейнер. Применяйте процедуру обновлений и к хосту, а не только к образам.
В сервисе compose это выглядит как user: "1000:1000", cap_drop: [ALL] и security_opt: ["no-new-privileges:true"].
Rootless-режим и обновления
Если вас устраивают его ограничения, rootless-режим уменьшает ущерб в худшем случае. В документации Docker сказано, что он позволяет запускать демон и контейнеры от имени обычного пользователя, чтобы снизить последствия потенциальных уязвимостей в демоне и среде выполнения контейнеров. Нужны newuidmap и newgidmap (обычно из пакета uidmap) и не менее 65 536 подчинённых UID и GID у пользователя в /etc/subuid и /etc/subgid. OWASP добавляет оговорку, которую стоит помнить: rootless-режим не защищает от уязвимостей ядра хоста.
Наконец, сделайте Docker частью обычной гигиены. Фиксируйте версии образов вместо latest, пересобирайте образы при обновлении базовых слоёв, удаляйте ненужные контейнеры и образы и время от времени просматривайте docker ps -a на предмет того, что вы не разворачивали. Неожиданные контейнеры классический признак компрометации, описанный в руководстве по реагированию на взлом, а поскольку журналы Docker-хоста тоже стоит отслеживать, логичный следующий шаг это руководство по мониторингу.
Если инструменту необходим доступ к API Docker, прокси сокета Docker ограничивает набор доступных вызовов, но сам по себе не делает сокет безопасным.
Часто задаваемые вопросы
Почему Docker игнорирует мои правила ufw?
Docker маршрутизирует трафик опубликованных портов через таблицу nat, поэтому пакеты перенаправляются до правил, которыми управляет ufw. По документации Docker, конфигурация файрвола для таких портов фактически игнорируется. Вместо этого привязывайте порты к 127.0.0.1 или фильтруйте в цепочке DOCKER-USER.
Как сделать так, чтобы контейнер не был доступен из интернета?
Публикуйте его только на адрес loopback, например -p 127.0.0.1:8080:80, либо вообще не публикуйте и поместите в пользовательскую сеть. Затем открывайте наружу только обратный прокси на портах 80 и 443.
Безопасно ли монтировать сокет Docker в контейнер?
Как правило, нет. Доступ к сокету равнозначен неограниченному root-доступу к хосту, а монтирование только для чтения не делает API Docker доступным только для чтения. Используйте его лишь для ПО, которому доверяете как root, либо поставьте между ними прокси сокета.
Безопасно ли добавлять пользователя в группу docker?
Считайте, что вы даёте ему root. Docker сообщает, что группа docker даёт пользователю привилегии уровня root, поэтому ограничьте её теми, кому доверили бы sudo.
Какие порты использует API Docker и нужно ли их открывать?
По умолчанию 2376 с TLS и 2375 без него. Публично их открывать нельзя. Для удалённого управления одним VPS используйте контекст Docker через SSH, который опирается на вашу защиту SSH.
Делает ли rootless Docker мой сервер безопасным?
Он снижает последствия уязвимостей в демоне и среде выполнения, запуская их без root, но не защищает от уязвимостей ядра хоста. Используйте его как один из слоёв вместе с обновлениями, файрволом и сбросом capabilities контейнеров.
Не уверены, в каком состоянии ваш сервер?
Получите бесплатную проверку безопасности в режиме только чтения или поговорите с инженером по безопасности об управляемой защите.
Получить бесплатную проверку сервера Связаться с инженером по безопасности