1. **Ограничить доступ к сокету Docker Daemon**. Владельцем сокет-файла должен быть пользователь root. Нужно понимать, что любой пользователь с доступом к сокету может получить доступ к системе. И запретить это можно, только если запретить маунтить файлы из определенных директорий. 2. **Не прокидывать сокет в контейнер **(Docker-in-Docker). Вместо Docker-in-Docker для сборки можно использовать kaniko — систему, которая позволит собрать образ без использования Docker. В этом случае для подписи образов можно использовать стороннюю систему и подключить ее через API. 3. ** Помнить о настройке авторизации Docker TCP**. Авторизацию настраиваем через сертификат SSL, то есть используем открытые и закрытые ключи и подписанные ключи по иерархии. Таким образом это все реализовано в Kubernetes. 4. **Настроить непривилегированного пользователя**. Запуск контейнеров всегда производим от непривилегированного пользователя. Если речь о Docker в чистом виде, мы просто указываем UID юзера и запускаем контейнер. ``` docker run -u 4000 alpine ``` Во время сборки контейнера мы создаем юзера и переходим на него. ``` FROM alpine RUN groupadd -r myuser && useradd -r -g myuser <Здесь еще можно выполнять команды от root-пользователя, например, ставить пакеты> USER myuser ``` Также включаем поддержку user namespace в Docker daemon. ``` --userns-remap=default ``` 5. **Отключить все возможности ядра** (capabilities). Например, так: ``` docker run --cap-drop all --cap-add CHOWN alpine ``` 6. **Запретить эскалацию привилегий** (смену юзера на uid0). Используем опцию при запуске: ``` --security-opt=no-new-privileges ``` 7. **Отключить межконтейнерное взаимодействие**. По умолчанию такое возможно через сеть docker0, опция при старте демона Docker: ``` --icc=false ``` 8. **Ограничить ресурсы**. Так мы сократим риск несанкционированного майнинга: ``` -m или --memory — доступная память до OOM; --cpus — сколько процессоров доступно, например 1.5; --cpuset-cpus — можно указать, какие именно процессоры доступны (ядра); --restart=on-failure:<number_of_restarts> — убираем вариант Restart Always, чтобы контролировать количество перезапусков и вовремя обнаруживать проблемы; --read-only — файловая система настраивается только на чтение при запуске, особенно если контейнер отдает статику. ``` 9. **Не отключать профили безопасности**. По умолчанию Docker уже использует профили для модулей безопасности Linux. Эти правила можно ужесточать, но не наоборот. Отдельно скажу несколько слов про seccomp — механизм ядра Linuх, позволяющий определять доступные системные вызовы. Если злоумышленник получит возможность выполнить произвольный код, seccomp не даст ему использовать системные вызовы, которые не были заранее разрешены. В стандартной поставке Docker блокирует около 44 вызовов из 300+. Кроме Seccomp можно использовать также профили AppArmor или SELinux. 10. **Анализировать содержимое контейнера**. Для обнаружения контейнеров с уже известными уязвимостями есть инструменты: бесплатный Clair, условно бесплатные Snyk, anchore, платные JFrog XRay и Qualys. Бесплатно уязвимости можно также учесть в Harbor: он ищет известные эксплойты и сообщает о надежности контейнера. Также можно использовать системы асессмента ИБ в целом, например, Open Policy agent.